package com.yanqu.road.server.manger.config;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.impl.curio.UserCurioSkillDataDaoImpl;
import com.yanqu.road.dao.impl.player.UserCombLeaderDaoImpl;
import com.yanqu.road.dao.impl.player.UserPatronsSkinBondDaoImpl;
import com.yanqu.road.dao.impl.player.UserVehicleBoneDaoImpl;
import com.yanqu.road.dao.impl.travelbook.TravelBookUserAlbumDaoImpl;
import com.yanqu.road.dao.impl.wingroom.UserFurnitureSuitDaoImpl;
import com.yanqu.road.entity.config.beauty.BeautyInfo;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.inn.DishesInfo;
import com.yanqu.road.entity.config.manor.ManorTechnologyConfig;
import com.yanqu.road.entity.config.patrons.*;
import com.yanqu.road.entity.config.promotion.PromotionInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skin.SkinInfo;
import com.yanqu.road.entity.config.travelbook.AlbumConfig;
import com.yanqu.road.entity.config.travelbook.CardConfig;
import com.yanqu.road.entity.config.vehicle.VehicleInfo;
import com.yanqu.road.entity.cricket.CricketData;
import com.yanqu.road.entity.cricket.CricketEquipSkill;
import com.yanqu.road.entity.cricket.config.CricketConfig;
import com.yanqu.road.entity.curio.UserCurioSkillData;
import com.yanqu.road.entity.curio.config.CurioItemInfo;
import com.yanqu.road.entity.curio.config.CurioItemSuitInfo;
import com.yanqu.road.entity.curio.enums.eCurioSkillType;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.extension.ExtensionWineryItemInfo;
import com.yanqu.road.entity.inn.UserDishes;
import com.yanqu.road.entity.manor.FishData;
import com.yanqu.road.entity.manor.ManorTechnologyData;
import com.yanqu.road.entity.player.*;
import com.yanqu.road.entity.servercenter.TitleInfo;
import com.yanqu.road.entity.travelbook.UserTravelAlbum;
import com.yanqu.road.entity.travelbook.UserTravelCard;
import com.yanqu.road.entity.wingroom.UserFurnitureSample;
import com.yanqu.road.entity.wingroom.UserFurnitureSuitData;
import com.yanqu.road.entity.wingroom.chakra.enums.WingRoomPositionTypeEnum;
import com.yanqu.road.entity.wingroom.config.WingRoomFurnitureConfig;
import com.yanqu.road.logic.bussiness.config.PatronsBussiness;
import com.yanqu.road.logic.bussiness.player.*;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.GameServer;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.cricket.CricketMgr;
import com.yanqu.road.server.gameplayer.module.patrons.PatronsModule;
import com.yanqu.road.server.logic.calc.CalculationManager;
import com.yanqu.road.server.manger.ConfigMgr;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.server.manger.activity.curio.CurioConfigMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.assistant.AssistantSkinMgr;
import com.yanqu.road.server.manger.manor.FishPondMgr;
import com.yanqu.road.server.manger.manor.ManorMgr;
import com.yanqu.road.server.manger.player.UserMgr;
import com.yanqu.road.server.manger.player.GamePlayerMgr;
import com.yanqu.road.server.manger.wingroom.WingRoomChakraMgr;
import com.yanqu.road.server.manger.wingroom.WingRoomConfigMgr;
import com.yanqu.road.server.pb.WorldMessagePb;
import com.yanqu.road.server.protocol.ClientProtocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 门客信息
 */
public class PatronsMgr extends TempMgr {

    private static Logger logger = LogManager.getLogger(PatronsMgr.class.getName());

    private static Map<Integer, PatronsInfo> patronsInfoMap;

    private static Map<Integer, PatronsUpgradeInfo> patronsUpgradeInfoMap;

    private static Map<Integer, PatronsBreak> patronsBreakMap;

    private static Map<Integer, PatronsStage> patronsStageMap;

    private static Map<Integer, CombInfo> patronsCombMap;

    private static Map<Integer, CombInfo> wuShuangPatronsCombMap;

    private static Map<Integer, List<String>> patronsOccupationListMap = new HashMap<>();
    private static RandomHelper randomHelper = new RandomHelper();

    private static Map<Integer, AlbumConfig> albumConfigMap = new HashMap<>(); // 旅行册卡册配置列表
    // 卡册Id -> (卡册升级列表(卡牌Id -> 卡牌等级)) 列表下标是卡册等级
    private static Map<Integer, List<Map<Integer, Integer>>> albumUpgradeMap = new HashMap<>();
    // 卡册Id -> (仪容技能额外等级上限列表(仪容技能Id -> 额外等级上限)) 列表下标是卡册等级
    private static Map<Integer, List<Map<Integer, Integer>>> skillExtendLevelMap = new HashMap<>();

    public static int getLinkType(int patronsId) {
        if(102501 == patronsId){//大陆葫芦仙人联动特殊处理
            int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
            if(eChannelType.isMainLandChannel(channelId)){
                return 1;
            }
        }else if(102502 == patronsId){//再加一个海外的杨戬
            int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
//            if(eChannelType.isTwChannel(channelId)
//                    || eChannelType.isKrChannel(channelId)
//                    || eChannelType.isJapanChannel(channelId)
//                    || eChannelType.isVnChannel(channelId)
//                    || eChannelType.isThinChannel(channelId)
//                    || 221 == channelId
//                    || 241 == channelId
//                    || 301 == channelId
//                    || 321 == channelId
//            ){
//                return 1;
//            }
            return 1;
        }
        PatronsInfo patronsInfo = getPatronsInfo(patronsId);
        if (patronsInfo != null) {
            long linkAge = patronsInfo.getLinkAge();
            if (System.currentTimeMillis() < linkAge) {
                return 1;
            }
        }
        return 0;
    }

    public static int randomPatronsId() {
        List<Integer> list = new ArrayList<>(patronsInfoMap.keySet());
        int index = randomHelper.next(0, list.size());
        return list.get(index);
    }

    public static List<Integer> getPatronsListByTypeAndQuality(Integer patronsType, Integer patronsQuality) {
        List<Integer> list = new ArrayList<>();
        for (PatronsInfo info : new ArrayList<>(patronsInfoMap.values())) {
            if (patronsType != 0 && info.getOccupation() != patronsType) {
                continue;
            }
            if (!HideGoodsMgr.getHideGoods().contains(info.getId())) {
                continue;
            }
            if (patronsQuality == info.getQuality()) {
                list.add(info.getId());
            }
        }
        return list;
    }

    @Override
    public boolean init() throws Exception {
        return reload();
    }

    @Override
    public boolean stop() {
        return false;
    }

    @Override
    public boolean save() {
        return false;
    }

    @Override
    public boolean reloadConfig() {
        patronsInfoMap = PatronsBussiness.getPatronsInfoMap();
        patronsUpgradeInfoMap = PatronsBussiness.getPatronsUpgradeInfoMap();
        patronsBreakMap = PatronsBussiness.getPatronsBreakMap();
        patronsStageMap = PatronsBussiness.getPatronsStageMap();
        wuShuangPatronsCombMap = PatronsBussiness.getPatronsCombMap(eCombType.Halo.getValue());
        Map<Integer, CombInfo> tempCombMap = PatronsBussiness.getPatronsCombMap(eCombType.Patrons.getValue());
        tempCombMap.putAll(wuShuangPatronsCombMap);
        initPatronsComb(tempCombMap);
        patronsCombMap = tempCombMap;
        if(patronsInfoMap.size() <= 0 || patronsUpgradeInfoMap.size() <= 0 || patronsStageMap.size() <=0 || patronsCombMap.size() <= 0 ||
                patronsBreakMap.size() <= 0){
            return false;
        }
        patronsOccupationListMap.clear();
        for (PatronsInfo patronsInfo : patronsInfoMap.values()) {
            if (!patronsOccupationListMap.containsKey(patronsInfo.getOccupation())) {
                patronsOccupationListMap.put(patronsInfo.getOccupation(), new ArrayList<>());
            }
            patronsOccupationListMap.get(patronsInfo.getOccupation()).add(String.valueOf(patronsInfo.getId()));
        }

        reloadTravelBookConfig();

        return true;
    }

    /**
     * 刷新旅行册配置
     */
    private static void reloadTravelBookConfig() {
        Map<Integer, CombInfo> travelBookAlbumMap = PatronsBussiness.getPatronsCombMap(eCombType.TravelBook.getValue());
        Map<Integer, AlbumConfig> tmpAlbumConfigMap = new HashMap<>();
        Map<Integer, List<Map<Integer, Integer>>> tmpAlbumUpgradeMap = new HashMap<>();
        Map<Integer, List<Map<Integer, Integer>>> tmpSkillExtendLevelMap = new HashMap<>();
        for (CombInfo combInfo : travelBookAlbumMap.values()) {
            int albumId = combInfo.getId();
            AlbumConfig album = new AlbumConfig();
            album.setBeautyId(Integer.parseInt(combInfo.getExtra()));
            album.setAlbumId(albumId);

            String advancedSkillId = combInfo.getAdvancedSkillId();
            // 170001=10;170101=2;71000=25#70100=4;70400=2;70500=2;70200=1|170001=20;170101=4;71000=50#70100=10;
            String[] levels = advancedSkillId.split("\\|");
            List<Map<Integer, Integer>> list1 = new ArrayList<>();
            List<Map<Integer, Integer>> list2 = new ArrayList<>();
            for (String level : levels) {
                String[] items = level.split("#"); // 170001=10;170101=2;71000=25#70100=4;70400=2;70500=2;70200=1
                String[] conditions1 = items[0].split(";"); // 170001=10;170101=2;71000=25
                Map<Integer, Integer> map1 = new HashMap<>();
                for (String condition : conditions1) {
                    String[] items1 = condition.split("="); // 170001=10
                    map1.put(Integer.parseInt(items1[0]), Integer.parseInt(items1[1]));
                }
                list1.add(map1);

                String[] conditions2 = items[1].split(";"); // 升级条件 70100=4;70400=2;70500=2;70200=1
                Map<Integer, Integer> map2 = new HashMap<>();
                for (String condition : conditions2) {
                    String[] items1 = condition.split("="); // 70100=4
                    map2.put(Integer.parseInt(items1[0]), Integer.parseInt(items1[1]));
                }
                list2.add(map2);
            }
            tmpSkillExtendLevelMap.put(albumId, list1);
            tmpAlbumUpgradeMap.put(albumId, list2);

            album.setCombInfo(combInfo);
            album.setSkillId(combInfo.getCombSkillId());
            tmpAlbumConfigMap.put(albumId, album);
        }
        albumConfigMap = tmpAlbumConfigMap;
        albumUpgradeMap = tmpAlbumUpgradeMap;
        skillExtendLevelMap = tmpSkillExtendLevelMap;
    }

    @Override
    public boolean reloadData() throws Exception {
        return true;
    }

    public static Map<Integer, PatronsInfo> getPatronsInfoMap() {
        return patronsInfoMap;
    }

    public static Map<Integer, CombInfo> getWuShuangPatronsCombMap() {
        return wuShuangPatronsCombMap;
    }

    /**
     * 初始化门客组合信息
     */
    private void initPatronsComb(Map<Integer, CombInfo> combMap){
        for(CombInfo combInfo : combMap.values()){
            List<Integer> patronsIdList = new ArrayList<>();
            for(PatronsInfo patronsInfo : patronsInfoMap.values()){
                if(combInfo.getId() == patronsInfo.getCombId()){
                    if(!patronsIdList.contains(patronsInfo.getId())){
                        patronsIdList.add(patronsInfo.getId());
                    }
                }
            }
            combInfo.setObjectIdList(patronsIdList);
        }
    }

    public static PatronsInfo getPatronsInfo(int patronsId) {
        return patronsInfoMap.get(patronsId);
    }

    public static PatronsUpgradeInfo getPatronsUpgradeInfo(int level){
        return patronsUpgradeInfoMap.get(level);
    }

    public static PatronsBreak getPatronsBreak(int breakLv) {
        return patronsBreakMap.get(breakLv);
    }

    public static PatronsStage getPatronsStage(int stageLv) {
        return patronsStageMap.get(stageLv);
    }

    public static CombInfo getPatronsComb(int combId){
        return patronsCombMap.get(combId);
    }

    /**
     * 门客组合是否解锁
     */
    public static boolean isUnlockPatronsComb(int patronsId, Map<Integer, UserPatrons> userPatronsMap){
        PatronsInfo patronsInfo = getPatronsInfo(patronsId);
        if(null == patronsInfo){
            return false;
        }
        if(patronsInfo.getCombId() <= 0){
            return false;
        }
        if(null == userPatronsMap){
            return false;
        }
        CombInfo combInfo = getPatronsComb(patronsInfo.getCombId());
        if(null == combInfo){
            return false;
        }
        //无双门客
        if (wuShuangPatronsCombMap.containsKey(combInfo.getId())) {
            UserPatrons userPatrons = userPatronsMap.get(patronsId);
            if (userPatrons == null) {
                return false;
            }
            UserPatronsSkill patronsSkill = userPatrons.getPatronsSkill(ePatronsSkillType.Comb.getValue(), combInfo.getCombSkillId());
            return patronsSkill != null;
        }
        if(null == combInfo.getObjectIdList() || combInfo.getObjectIdList().size() <= 0){
            return false;
        }
        for(int patrons : combInfo.getObjectIdList()){
            if(!userPatronsMap.containsKey(patrons)){
                return false;
            }
        }
        return true;
    }

    /**
     * 门客升级消耗
     */
    public static Property getPatronsUpgradeConsume(PatronsUpgradeInfo patronsUpgradeInfo, int upgradeParam, int goodsIndex){
        Property consume = new Property();
        if(null == patronsUpgradeInfo){
            return consume;
        }
        Property infoConsume = patronsUpgradeInfo.getConsume();
        if(goodsIndex == 1){
            infoConsume = patronsUpgradeInfo.getConsumeNew();
        }
        for (Map.Entry<Integer, BigInteger> goodsEntry : infoConsume.getGoods().entrySet()) {
            BigDecimal costCount = new BigDecimal(goodsEntry.getValue());
            costCount = costCount.multiply(BigDecimal.valueOf((double)upgradeParam / 1000)).setScale(0, BigDecimal.ROUND_UP);
            consume.addProperty(goodsEntry.getKey(), costCount.toBigInteger());
        }
        return consume;
    }

    /**
     * 获取门客集合实力
     */
    public static BigInteger getPatronsListAbility(long userId, List<Integer> patronsIdList){
        if(null == patronsIdList || patronsIdList.size() <= 0){
            return BigInteger.ZERO;
        }

        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if(null != player){
            return player.getModule(PatronsModule.class).getPatronsListAbility(patronsIdList);
        }else {
            BigInteger totalAbility = BigInteger.ZERO;
            Map<Integer, UserPatrons> userPatronsMap = UserPatronsBussiness.getUserPatronsMap(userId);
            for(int patronsId : patronsIdList){
                UserPatrons userPatrons = userPatronsMap.get(patronsId);
                if(null != userPatrons){
                    totalAbility = totalAbility.add(userPatrons.getAbility());
                }
            }
            return totalAbility;
        }
    }

    public static BigInteger getPatronsListAbility(List<UserPatrons> patronsList){
        if(null == patronsList){
            return BigInteger.ZERO;
        }

        BigInteger totalAbility = BigInteger.ZERO;
        for(UserPatrons userPatrons : patronsList){
            if(null != userPatrons){
                totalAbility = totalAbility.add(userPatrons.getAbility());
            }
        }
        return totalAbility;
    }

    //盐场战斗算上技能加成后的赚速能力
    public static BigInteger getOreWarPatronsListEarnSpeed(List<UserPatrons> patronsList){
        if(null == patronsList){
            return BigInteger.ZERO;
        }

        BigInteger totalAbility = BigInteger.ZERO;
        for(UserPatrons userPatrons : patronsList){
            if(null != userPatrons){
                totalAbility = totalAbility.add(userPatrons.getOreWarEarnSpeed());
            }
        }
        return totalAbility;
    }

    public static BigInteger getPatronsTotalAbility(long userId){
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if(null != player){
            return player.getModule(PatronsModule.class).getTotalPatronsAbility();
        }else {
            BigInteger totalAbility = BigInteger.ZERO;
            Map<Integer, UserPatrons> userPatronsMap = UserPatronsBussiness.getUserPatronsMap(userId);
            for(UserPatrons userPatrons : userPatronsMap.values()){
                totalAbility = totalAbility.add(userPatrons.getAbility());
            }
            return totalAbility;
        }
    }

    public static long getPatronsTotalQualification(long userId){
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if(null != player){
            return player.getModule(PatronsModule.class).getTotalQualification();
        }else {
            long qualification = 0;
            Map<Integer, UserPatrons> userPatronsMap = UserPatronsBussiness.getUserPatronsMap(userId);
            for(UserPatrons userPatrons : userPatronsMap.values()){
                qualification += userPatrons.getTotalQualification();
            }
            return qualification;
        }
    }

    public static Map<Integer, UserPatrons> getUserPatronsMap(long userId){
        GamePlayer player = GamePlayerMgr.getOnlinePlayer(userId);
        if (null != player) {
            return player.getModule(PatronsModule.class).getUserPatronsMap();
        } else {
            return UserPatronsBussiness.getUserPatronsMap(userId);
        }
    }

    public static Map<Long, Map<Integer, UserPatrons>> getSomeUserPatronsMap(List<Long> userIdList) {
        return UserPatronsBussiness.getSomeUserPatronsMap(userIdList);
    }

    public static PatronsAbilityCalcBaseParams calcPatronsAbilityCalcBaseParams(UserPatrons userPatrons, CalcPatronsAbilityParam param) {
        return calcPatronsAbilityCalcBaseParams(userPatrons, param, false);
    }

    public static PatronsAbilityCalcBaseParams calcPatronsAbilityCalcBaseParams(UserPatrons userPatrons, CalcPatronsAbilityParam param, boolean isPrintf) {
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());

        StringBuilder printfStr = new StringBuilder();

        //品质 //这里patronsInfo不判空,是因为有门客动态数据,肯定有门客配置,如果没有就是配置不一致,抛异常
        int quality = getPatronsQuality(userPatrons);

        long qualification = getPatronsQualification(userPatrons, param);

        //信物羁绊加资质
        long keepSakeAddition = 0;
        int keepSakePatronsId = userPatrons.getShowKeepSakePatronsId();
        if (keepSakePatronsId != 0) {
            keepSakeAddition = calKeepSakeQualificationAddition(userPatrons, param.getPatronsMap(), keepSakePatronsId);
        }

        BigDecimal x1 = BigDecimal.valueOf((double) ConfigMgr.getPatronsAbilityParam1() / 1000000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
        BigDecimal x2 = BigDecimal.valueOf((double) ConfigMgr.getPatronsAbilityParam2() / 1000000 * userPatrons.getLevel() * userPatrons.getLevel()).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
        BigDecimal x3 = BigDecimal.valueOf((double) ConfigMgr.getPatronsAbilityParam3() / 1000000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
        BigDecimal x4 = BigDecimal.valueOf(Math.pow(userPatrons.getLevel(), (double) ConfigMgr.getPatronsAbilityParam4() / 1000)).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
        //缓存计算赚钱能力的参数
        BigDecimal calcAbilityParam = x1.add(x2).add(x3.multiply(x4));

        //组合加成
        int combAddition = getCombAddition(userPatrons);
        BigDecimal k1 = BigDecimal.valueOf((double) combAddition / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //座骑加成
        int curioAddition = 0;
        if (patronsInfo != null) {
            curioAddition = (int) getCurioSkillAdd(userPatrons, param.getCurioSkillDataMap(), eSkillType.OccupationSoulStoneAddSkill.getValue(), patronsInfo.getOccupation());
        }
        double vehicleAddition = getVehicleAddition(userPatrons, param.getVehicleMap(), param.getVehicleSoulMap(), curioAddition, param.getVehicleBoneMap());
        BigDecimal k2 = BigDecimal.valueOf(vehicleAddition / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        int stageAddition = 0;
        PatronsStage patronsStage = getPatronsStage(userPatrons.getStageLv());
        if (null != patronsStage) {
            stageAddition = patronsStage.getAddAbilityAddition();
        }
        //精进加成
        BigDecimal k3 = BigDecimal.valueOf((double) stageAddition / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //美女门客技能百分比加成
        BigDecimal k4 = BigDecimal.valueOf((double) getBeautyAddPercentage(userPatrons, param.getBeautyMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //技能buff加成
        BigDecimal k5 = BigDecimal.valueOf(getAddPatronsAbilityAddition(userPatrons, param.getBeautyMap(), param.getPatronsMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //组合门客加成
        BigDecimal k6 = BigDecimal.valueOf((double) getCombPatronsAbilityAddValue(patronsInfo.getCombId(), param.getPatronsMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //美女皮肤技能加成
        //美女门客技能百分比加成
        BigDecimal k7 = BigDecimal.valueOf(getSkinBeautySkillAddAbility(userPatrons, patronsInfo, param.getBeautyMap(), eSkillType.SkinBeautySkillAddPatronsAbilityAddition.getValue())).
                divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //鱼加成
        BigDecimal k8 = BigDecimal.valueOf((double) FishPondMgr.getFishAddPercentage(patronsInfo.getId(), param.getFishDataMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //厢房加成
        BigDecimal k9 = BigDecimal.valueOf((double) getWingRoomAddPercentage(patronsInfo.getOccupation(), param.getSuitDataMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //门客皮肤羁绊光环加千分比加成
        BigDecimal k10 = BigDecimal.valueOf((double) SkinMgr.getPatronsSkinBondCombAddValue(patronsInfo.getId(), param.getUserPatronsSkinBondMap(), param.getUserSkinMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //信物系统-羁绊加千分比
        BigDecimal k11 = BigDecimal.valueOf(getKeepSakeEarnAddition(userPatrons, param.getPatronsMap())).divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        // 服装-服装加千分比
        BigDecimal k12 = BigDecimal.valueOf(getSpecialPatronsEarnAddition(userPatrons, param.getUserSkinMap(), quality)).divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //厢房命盘-门客赚钱加成千分比
        BigDecimal k13 = BigDecimal.valueOf(getWingRoomChakraEarnAddition(userPatrons.getPatronsId(), param.getWingRoomChakraAbilityAddMap())).divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        // 藏品千分比
        // 无双门客+套装门客+特定门客+特定职业门客
        Map<Integer, Integer> curioSkillCheckMap =new HashMap<>();
        curioSkillCheckMap.put(eSkillType.CurioComPatronsEarnAddSkill.getValue(), userPatrons.getPatronsId());
        curioSkillCheckMap.put(eSkillType.CurioPatronsEarnAddSkill.getValue(), userPatrons.getPatronsId());
        curioSkillCheckMap.put(eSkillType.SpecialPatronsEarnAddSkill.getValue(), patronsInfo.getOccupation());
        curioSkillCheckMap.put(eSkillType.CurioPeerlessPatronsEarnAddSkill.getValue(), quality);
        if (isCombLeader(patronsInfo, param.getCombLeaderDataMap())) {
            curioSkillCheckMap.put(eSkillType.CurioSkill335.getValue(), patronsInfo.getCombId());
        }
        BigDecimal k14 = BigDecimal.valueOf(getCurioSkillAdd(userPatrons, param.getCurioSkillDataMap(), curioSkillCheckMap))
                .divide(BigDecimal.valueOf(1000), CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        //小舞加成
        BigDecimal xiaowuAdd = BigDecimal.valueOf((double) getXiaoWuPatronsAbilityAddValue(patronsInfo.getId(), param.getPatronsMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        // 旅行册千分比加成
        BigDecimal travelBookAddPerm = BigDecimal.valueOf((double) getTravelBookAddPerm(userPatrons,
                param.getTravelBookBeautyMap(), param.getBeautyMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE,
                RoundingMode.UP);

        //通用技能赚钱千分比加成
        int commonRateAdd = getCommonRateAddition(userPatrons);
        BigDecimal commonRateAddBig = BigDecimal.valueOf((double) commonRateAdd / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

        BigDecimal abilityAdditionRatio =
                k1.add(k2).add(k3).add(k4).add(k5).add(k6).add(k7).add(k8).add(k9).add(k10).add(k11).add(k12).add(k13).add(k14).add(xiaowuAdd).add(travelBookAddPerm).add(commonRateAddBig);

        PatronsAbilityCalcBaseParams patronsAbilityCalcBaseParams = new PatronsAbilityCalcBaseParams(userPatrons, quality, qualification, keepSakeAddition, calcAbilityParam, abilityAdditionRatio);


        if (isPrintf) {
            printfStr.append("组合加成：").append(k1).append("\n");
            printfStr.append("座骑加成：").append(k2).append("\n");
            printfStr.append("精进加成：").append(k3).append("\n");
            printfStr.append("美女门客技能百分比加成：").append(k4).append("\n");
            printfStr.append("技能buff加成：").append(k5).append("\n");
            printfStr.append("组合门客加成：").append(k6).append("\n");
            printfStr.append("美女皮肤技能加成：").append(k7).append("\n");
            printfStr.append("鱼加成：").append(k8).append("\n");
            printfStr.append("厢房加成：").append(k9).append("\n");
            printfStr.append("门客皮肤羁绊光环加成：").append(k10).append("\n");
            printfStr.append("信物系统-羁绊加成：").append(k11).append("\n");
            printfStr.append("服装加成：").append(k12).append("\n");
            printfStr.append("厢房命盘-加成：").append(k13).append("\n");
            printfStr.append("藏品加成：").append(k14).append("\n");
            printfStr.append("小舞加成：").append(xiaowuAdd).append("\n");
            printfStr.append("总千分比加成：").append(abilityAdditionRatio).append("\n");
            printfStr.append("每点资质赚钱：").append(calcAbilityParam).append("\n");
            printfStr.append("无信物总资质：").append(qualification).append("\n");
            printfStr.append("信物资质：").append(keepSakeAddition).append("\n");
            printfStr.append("旅行册加成：").append(travelBookAddPerm).append("\n");
            printfStr.append("技能千分比加成：").append(commonRateAddBig).append("\n");
            patronsAbilityCalcBaseParams.setPrintfStr(printfStr.toString());
        }

        return patronsAbilityCalcBaseParams;
    }

    /**
     * 旅行册缘分门客赚钱增加千分比-卡牌技能
     *
     * @param patron         门客
     * @param beautyAlbumMap 美女旅行册
     * @param beautyMap      美女
     * @return 增加千分比
     */
    private static long getTravelBookAddPerm(UserPatrons patron,
                                             Map<Integer, List<UserTravelAlbum>> beautyAlbumMap,
                                             Map<Integer, UserBeauty> beautyMap) {
        long addition = 0;

        for (Map.Entry<Integer, List<UserTravelAlbum>> kv : beautyAlbumMap.entrySet()) {
            int beautyId = kv.getKey();
            if (!beautyMap.containsKey(beautyId)) {
                continue;
            }
            UserBeauty beauty = beautyMap.get(beautyId);
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, patron)) {
                for (UserTravelAlbum album : kv.getValue()) {
                    for (UserTravelCard card : album.getCards()) {
                        int cardId = card.getCardId();
                        int cardLevel = card.getLevel();
                        CardConfig cardConfig = TravelBookConfigMgr.getCardInfo(cardId);
                        if (cardConfig == null) {
                            continue;
                        }
                        SkillInfo skillInfo = cardConfig.getSkillInfo();
                        if (skillInfo == null
                                || skillInfo.getType() != eSkillType.TravelCardEarnSpeedPerm.getValue()
                                || card.getPatronId() != patron.getPatronsId()) {
                            continue;
                        }
                        long tmp = SkillMgr.getSkillAddition(skillInfo, cardLevel);
                        addition += tmp;
                    }
                }
            }
        }

        return addition;
    }

    /**
     * 获取门客赚钱能力
     *
     * @param userPatrons
     * @param param
     */
    public static BigInteger getPatronsAbility(UserPatrons userPatrons, CalcPatronsAbilityParam param) {
        BigInteger ability;

        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());

        PatronsAbilityCalcBaseParams calcBaseParams = calcPatronsAbilityCalcBaseParams(userPatrons, param);

        //缓存到门客身上
        userPatrons.setCalcAbilityParam(calcBaseParams.getCalcAbilityParam());
        BigDecimal baseAbility = calcBaseParams.calcBaseAbility();
        userPatrons.setBaseAbility(baseAbility);
        userPatrons.setQualification(calcBaseParams.getQualification());//这里不包含羁绊资质
        userPatrons.setKeepSakeAddition(calcBaseParams.getKeepSakeQualification());

        //精进增加能力值
        BigDecimal g1 = BigDecimal.ZERO;
        PatronsStage patronsStage = getPatronsStage(userPatrons.getStageLv());
        if (null != patronsStage) {
            g1 = new BigDecimal(patronsStage.getAddAbility());
        }
        //美女门客技能增加固定值
        BigDecimal g3 = BigDecimal.valueOf(getBeautyAddRegular(userPatrons, param.getBeautyMap()));

        //美女走镖技能增加固定值
        BigDecimal g4 = BigDecimal.valueOf((double) getBeautyEscortAddRegular(userPatrons, param.getBeautyMap()));

        //美女妙音坊技能增加固定值
        BigDecimal musicRoomAdd = BigDecimal.valueOf((double) getBeautyMusicRoomAddRegular(userPatrons, param.getBeautyMap()));

        //藏宝系统技能特定职业增加固定值
        BigDecimal curioAdd = BigDecimal.valueOf(getCurioSkillAdd(userPatrons, param.getCurioSkillDataMap(), eSkillType.CurioPatronsAbilitySkill.getValue(), patronsInfo.getOccupation()));

        BigDecimal abilityAdditionRatio = calcBaseParams.getAbilityAdditionRatio();
        userPatrons.setAbilityAdditionRatio(abilityAdditionRatio);

        //算出原美女缘分技能增加的赚钱值，再算美女无双技能生效的值。
        BigDecimal peerlessSkillAddition = BeautyMgr.getAllBeautyPeerlessSkillAddition(userPatrons, param.getBeautyMap(), baseAbility,
                calcBaseParams.getCalcAbilityParam(), abilityAdditionRatio);

        //契约美女加的固定值
        BigDecimal contractAddition = calcPatronsContractTotalAbility(userPatrons, param);

        //计算实力
        BigDecimal result = baseAbility.multiply(BigDecimal.ONE.add(abilityAdditionRatio)).add(g1).add(g3).add(g4).add(musicRoomAdd).add(curioAdd).add(peerlessSkillAddition).add(contractAddition);
        ability = result.setScale(0, BigDecimal.ROUND_UP).toBigInteger();
        //g2
        ability = ability.add(userPatrons.getAddAbility());
        //门客商战胜利增加值 g4
        ability = ability.add(userPatrons.getTradeWarAddEarnSpeed());
//        logger.info("userId:{};patronsId:{};level:{};patronsAbility:{}", userPatrons.getUserId(), userPatrons.getPatronsId(), userPatrons.getLevel(),
//                ability.toString());

        //食谱加成固定值 g5
        BigInteger g5 = BigInteger.valueOf(getDishesAddRegular(patronsInfo.getOccupation(), param.getUserDishesMap()));
        ability = ability.add(g5);

        //庄园加成固定值 g6
        BigInteger g6 = BigInteger.valueOf(getManorPatronsAbilityAddValue(patronsInfo.getId(), param.getManorTechnologyDataMap()));
        ability = ability.add(g6);

        //装备鱼类加成固定值 g7
        BigInteger g7 = BigInteger.valueOf(FishPondMgr.getFishAbilityAddValue(patronsInfo.getId(), param.getFishDataMap()));
        ability = ability.add(g7);

        //孙子职业技能加能力
        BigInteger g8 = getGrandChildProfessionAddAbility(patronsInfo.getOccupation(), param.getGrandChildProfessionSkillAdditionMap());
        ability = ability.add(g8);

        ability = ability.add(userPatrons.getGrandChildSpeed());

        userPatrons.setShowGrandSpeed(userPatrons.getGrandChildSpeed().add(g8));

        //厢房加能力固定值
        BigInteger g9 = getWingRoomAddAbility(patronsInfo.getOccupation(), param.getFurnitureMap());
        ability = ability.add(g9);

        BigInteger wineryAddAbility = getWineryAddAbility(patronsInfo.getOccupation(), param.getWineryItemInfoMap());
        ability = ability.add(wineryAddAbility);

        BigInteger cricketAddAbility = getCricketAddAbility(userPatrons);
        ability = ability.add(cricketAddAbility);

        //魂骨加固定值
        BigInteger vehicleBoneAddAbility = getVehicleBoneAddAbility(userPatrons, param.getVehicleMap(), param.getVehicleBoneMap());
        ability = ability.add(vehicleBoneAddAbility);

        // 旅行册卡牌加固定值
        BigInteger travelBookAddFixedValue = getTravelBookAddFixedValue(userPatrons, param.getTravelBookBeautyMap(),
                param.getBeautyMap());
        ability = ability.add(travelBookAddFixedValue);

        long tradeWarLoseScoreReduce = getTradeWarLoseScoreReduce(userPatrons);

        userPatrons.setAbility(ability);
        userPatrons.setTradeWarLoseScoreReduce(tradeWarLoseScoreReduce);
        return ability;
    }

    /**
     * 旅行册美女卡牌技能增加固定值
     *
     * @param patron         门客
     * @param beautyAlbumMap 美女旅行册
     * @param beautyMap      美女
     * @return 增加固定值
     */
    private static BigInteger getTravelBookAddFixedValue(UserPatrons patron,
                                                         Map<Integer, List<UserTravelAlbum>> beautyAlbumMap,
                                                         Map<Integer, UserBeauty> beautyMap) {
        long addition = 0;

        for (Map.Entry<Integer, List<UserTravelAlbum>> kv : beautyAlbumMap.entrySet()) {
            int beautyId = kv.getKey();
            if (!beautyMap.containsKey(beautyId)) {
                continue;
            }
            UserBeauty beauty = beautyMap.get(beautyId);
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, patron)) {
                for (UserTravelAlbum album : kv.getValue()) {
                    for (UserTravelCard card : album.getCards()) {
                        int cardId = card.getCardId();
                        int cardLevel = card.getLevel();
                        CardConfig cardConfig = TravelBookConfigMgr.getCardInfo(cardId);
                        if (cardConfig == null) {
                            continue;
                        }
                        SkillInfo skillInfo = cardConfig.getSkillInfo();
                        if (skillInfo == null
                                || skillInfo.getType() != eSkillType.TravelCardEarnSpeedFixedValue.getValue()) {
                            continue;
                        }
                        long tmp = SkillMgr.getSkillAddition(skillInfo, cardLevel);
                        addition += tmp;
                    }
                }
            }
        }

        return BigInteger.valueOf(addition);
    }

    //信物羁绊 给被羁绊加赚钱
    private static long getKeepSakeEarnAddition(UserPatrons userPatrons, Map<Integer, UserPatrons> patronsMap) {
        long addition = 0L;
        for (Map.Entry<Integer, UserPatrons> entry : patronsMap.entrySet()) {
            UserPatrons patrons = entry.getValue();
            if (patrons.getPatronsId() == userPatrons.getPatronsId()) {
                continue;
            }
            if (patrons.getShowKeepSakePatronsId() == userPatrons.getPatronsId()) {
                PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(patrons.getPatronsId());
                if (patronsInfo != null) {
                    UserPatronsSkill patronsSkill = patrons.getPatronsSkill(patronsInfo.getKeepsake());
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsInfo.getKeepsake());
                    if (patronsSkill != null && skillInfo != null) {
                        addition += skillInfo.getParamList().get(1);
                    }
                }
            }
        }
        return addition;
    }

    /**
     * 厢房命盘-门客赚钱加成千分比
     * @param patronsId
     * @param wingRoomChakraQualificationAddMap
     * @return
     */
    private static long getWingRoomChakraEarnAddition(int patronsId, Map<Integer, Long> wingRoomChakraQualificationAddMap) {
        return wingRoomChakraQualificationAddMap.getOrDefault(patronsId, 0L);
    }

    //兽魂加赚钱千分比
    private static long getVehicleSoulEarnAddition(UserPatrons userPatrons, Map<String, UserVehicle> userVehicleMap, Map<Integer, UserVehicleSoul> userVehicleSoulMap, int curioSkillAdd) {
        UserVehicle userVehicle = null;
        for(UserVehicle tmpVehicle : userVehicleMap.values()){
            if(tmpVehicle.getPatronsId() == userPatrons.getPatronsId()){
                userVehicle = tmpVehicle;
                break;
            }
        }
        if(userVehicle == null){
            return 0;
        }
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        if(vehicleInfo.getQuality() < 6){
            //不是無雙的直接不用算了，減少消耗
            return 0;
        }
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
        int blockCount = userVehicle.getSoulBlockList().size();//孔的个数
        if(blockCount == 0){
            return 0;
        }
        int blockInCount = 0;//孔被填装的数目
        int blockInRightCount = 0;//孔被填装的有对应职业加成数目
        for(UserVehicleSoul userVehicleSoul : userVehicleSoulMap.values()){
            if(userVehicleSoul.getVehicleId().equals(userVehicle.getVehicleUid())){
                blockInCount += userVehicleSoul.getOccList().size();
                List<Integer> occList = userVehicleSoul.getOccList();
                for(int occId : occList){
                    if(occId == patronsInfo.getOccupation()){
                        blockInRightCount += 1;
                    }
                }
            }
        }
        List<Integer> paramList = VehicleSoulMgr.getEarnSpeedAddValueList(blockCount,blockCount == blockInCount);
        if(paramList.size() == 2){
            long addValue = (paramList.get(0) + curioSkillAdd) * blockInRightCount + paramList.get(1);
            return addValue;
        }
        return 0;
    }

    //兽魂加赚钱千分比把加成和满盘分开，做日志不上上面那个了
    public static List<Integer> getVehicleSoulEarnAdditionList(UserPatrons userPatrons, UserVehicle userVehicle, Map<Integer, UserVehicleSoul> userVehicleSoulMap, int addition) {
        List<Integer> resList = new ArrayList<>();
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        if(vehicleInfo.getQuality() < 6){
            //不是無雙的直接不用算了，減少消耗
            return resList;
        }
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
        int blockCount = userVehicle.getSoulBlockList().size();//孔的个数
        if(blockCount == 0){
            return resList;
        }
        int blockInCount = 0;//孔被填装的数目
        int blockInRightCount = 0;//孔被填装的有对应职业加成数目
        for(UserVehicleSoul userVehicleSoul : userVehicleSoulMap.values()){
            if(userVehicleSoul.getVehicleId().equals(userVehicle.getVehicleUid())){
                blockInCount += userVehicleSoul.getOccList().size();
                List<Integer> occList = userVehicleSoul.getOccList();
                for(int occId : occList){
                    if(occId == patronsInfo.getOccupation()){
                        blockInRightCount += 1;
                    }
                }
            }
        }
        List<Integer> paramList = VehicleSoulMgr.getEarnSpeedAddValueList(blockCount,blockCount == blockInCount);
        if(paramList.size() == 2){
            List<Integer> addList = new ArrayList<>();
            addList.add(paramList.get(0) * blockInRightCount + addition * blockInRightCount);
            addList.add(paramList.get(1));
            return addList;
        }
        return resList;
    }

    //信物羁绊 加资质
    private static long calKeepSakeQualificationAddition(UserPatrons userPatrons, Map<Integer, UserPatrons> patronsMap, int keepSakePatronsId) {
        //被羁绊门客
        UserPatrons keepSakePatrons = patronsMap.get(keepSakePatronsId);
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        if (keepSakePatrons != null && patronsInfo != null) {
            //我的羁绊技能
            UserPatronsSkill patronsSkill = userPatrons.getPatronsSkill(patronsInfo.getKeepsake());
            if (patronsSkill != null) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                if (skillInfo != null) {
                    //被羁绊门客的每100点资质  给我提升1点
                    return keepSakePatrons.getQualification() / skillInfo.getUpgradeParamList().get(0) * skillInfo.getUpgradeParamList().get(1);
                }
            }
        }
        return 0;
    }

    private static long getCombPatronsAbilityAddValue(int combId, Map<Integer, UserPatrons> patronsMap) {
        int addition = 0;
        for (UserPatrons patrons : patronsMap.values()) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if (skillInfo != null) {
                    if (skillInfo.getType() == eSkillType.CombPatronsEarnSpeedAddition.getValue() && skillInfo.getParamList().get(2) == combId) {
                        addition += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                    }
                }
            }
        }
        return addition;
    }

    /**
     * 小舞技能,可以给其他门客加
     *
     * @param patronsId
     * @param patronsMap
     * @return
     */
    private static long getXiaoWuPatronsAbilityAddValue(int patronsId, Map<Integer, UserPatrons> patronsMap) {
        int addition = 0;
        for (UserPatrons patrons : patronsMap.values()) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if (skillInfo != null) {
                    //指定门客技能
                    if (skillInfo.getType() == eSkillType.Skill249.getValue() && skillInfo.getParamList().contains(patronsId)) {
                        addition += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                    }
                }
            }
        }
        return addition;
    }

    private static long getTradeWarLoseScoreReduce(UserPatrons userPatrons) {
        if (userPatrons == null) {
            return 0;
        }
        long tradeWarLoseScoreReduce = 0;
        if (null != userPatrons.getSkillList()) {
            for (UserPatronsSkill patronsSkill : userPatrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                if (skillInfo == null) {
                    continue;
                }
                if(skillInfo.getType() == eSkillType.TradeWarLoseScoreReduce.getValue()){
                    tradeWarLoseScoreReduce += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
            }
        }
        return tradeWarLoseScoreReduce;
    }

    //获取食谱加成
    private static long getDishesAddRegular(int occupation , Map<Integer, UserDishes> userDishesMap) {
        if (null == userDishesMap) return 0;

        long result = 0;

        for(Map.Entry<Integer,UserDishes> entry: userDishesMap.entrySet()){
            DishesInfo dishes = DishesMgr.getDishes(entry.getKey());
            if(null != dishes ){
                //技能信息
                SkillInfo skillInfo = SkillMgr.getSkillInfo(dishes.getSkillId());
                //对应的门客加成
                if(null == skillInfo){
                    continue;
                }
                int param3 = skillInfo.getParamList().get(2);
                if (param3 == occupation || param3 == 0) {
                    int level = entry.getValue().getLevel();
                    int skillAddition = SkillMgr.getSkillAddition(skillInfo, level);
                    result = skillAddition + result;
                }
            }
        }
        return result;
    }

    //获取庄园门客赚钱加成固定值
    private static long getManorPatronsAbilityAddValue(int patronsId, Map<Integer, ManorTechnologyData> technologyDataMap) {
        return ManorMgr.getManorAddValue(patronsId, technologyDataMap, eSkillType.ManorPatronsAbilityAddValue.getValue());
    }

    //获取庄园门客资质提升固定值
    private static long getManorPatronsQualificationAddValue(int patronsId, Map<Integer, ManorTechnologyData> technologyDataMap) {
        return ManorMgr.getManorAddValue(patronsId, technologyDataMap, eSkillType.ManorPatronsQualificationAddValue.getValue());
    }

    /**
     * 门客组合加成
     */
    private static int getCombAddition(UserPatrons userPatrons) {
        int addition = 0;
        if (null == userPatrons) {
            return addition;
        }

        List<UserPatronsSkill> skillList = userPatrons.getSkillList();
        for (UserPatronsSkill patronsSkill : skillList) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
            if (skillInfo == null) {
                continue;
            }
            //组合技能
            if (patronsSkill.getType() == ePatronsSkillType.Comb.getValue() || patronsSkill.getType() == ePatronsSkillType.PatronsSkinComb.getValue()) {
                if (eSkillType.Ability.getValue() == skillInfo.getType()) {
                    addition += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
                }
            }
//            //处理刘昂星中华一番极技能热更临时处理
//            if (userPatrons.getPatronsId() == 102531
//                    && patronsSkill.getSkillId() == 31711
//                    && skillInfo.getType() == eSkillType.Ability.getValue()) {
//                addition += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
//            }
        }
//        logger.info("patronsId:{},combAddition:{}", userPatrons.getPatronsId(), addition);
        return addition;
    }

    /**
     * 通用技能赚钱千分比加成
     * @param userPatrons
     * @return
     */
    private static int getCommonRateAddition(UserPatrons userPatrons) {
        int addition = 0;
        if (null == userPatrons) {
            return addition;
        }
        List<UserPatronsSkill> skillList = userPatrons.getSkillList();
        for (UserPatronsSkill patronsSkill : skillList) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
            if (skillInfo == null) {
                continue;
            }
            if (eSkillType.PatronsSkillCommonAbility.getValue() == skillInfo.getType()) {
                addition += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
            }
        }
        return addition;
    }

    //缘分技能加成赚速百分比
    private static int getCricketFateAddRatio(UserPatrons userPatrons) {
        int addition = 0;
        if (null == userPatrons) {
            return addition;
        }
        SkillInfo skillInfo;
        List<UserPatronsSkill> skillList = userPatrons.getSkillList();
        for (UserPatronsSkill patronsSkill : skillList) {
            //组合技能
            if (SkillMgr.isPatronsCricketFateSkill(patronsSkill.getSkillId())) {
                skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                if (null != skillInfo && eSkillType.Ability.getValue() == skillInfo.getType()) {
                    addition += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
                }
            }
        }
//        logger.info("patronsId:{},combAddition:{}", userPatrons.getPatronsId(), addition);
        return addition;
    }

    /**
     * 身份加成
     */
    private static double getTitleAddition(UserPatrons userPatrons){
        double addition = 0;
        if(null == userPatrons){
            return addition;
        }
        UserInfo userInfo = UserMgr.getUserInfo(userPatrons.getUserId());
        if(null == userInfo){
            return addition;
        }
        TitleInfo titleInfo = TitleMgr.getTitleInfo(userInfo.getTitleId());
        if(null == titleInfo){
            return addition;
        }

        addition = titleInfo.getPatronsAbilityAddition();
//        logger.info("titleAddition:{}", addition);
        return addition;
    }

    /**
     * 座骑加成
     */
    public static double getVehicleAddition(UserPatrons userPatrons, Map<String, UserVehicle> vehicleMap, Map<Integer, UserVehicleSoul> userVehicleSoulMap, int curioAddition, Map<Integer, UserVehicleBone> boneMap) {
        double addition = 0;
        if (null == userPatrons) {
            return addition;
        }
        if (null == vehicleMap) {
            return addition;
        }
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        if (null == patronsInfo) {
            return addition;
        }
        UserVehicle userVehicle = null;
        for (UserVehicle vehicle : vehicleMap.values()) {
            if(vehicle.getPatronsId() == userPatrons.getPatronsId() && !vehicle.isDelete()){
                userVehicle = vehicle;
                break;
            }
        }
        if(null == userVehicle) {
            return addition;
        }
        for(UserVehicleSkill vehicleSkill : userVehicle.getSkillMapEffect().values()){
            if (patronsInfo.getOccupation() == vehicleSkill.getSkillType()) {
                addition = addition + vehicleSkill.getValue() * 10;
            }
        }

        //组合珍兽光环加成
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        if(vehicleInfo.getCombId() > 0){
            addition = addition + VehicleMgr.getCombAddition(userVehicle);
        }
        addition = addition + getVehicleSoulEarnAddition(userPatrons, vehicleMap, userVehicleSoulMap, curioAddition);
        addition += getVehicleBoneAddition(userPatrons, vehicleMap, boneMap, curioAddition);

//        logger.info("vehicleAddition:{}", addition);
        return addition;
    }

    /**
     * 取得门客资质
     */
    public static long getPatronsQualification(UserPatrons userPatrons, CalcPatronsAbilityParam param) {
        if(null == userPatrons){
            return 0;
        }
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        if(null == patronsInfo){
            return 0;
        }
        //品质
        int quality = patronsInfo.getQuality();
        long qualification = patronsInfo.getQualification();
        int promotionId = userPatrons.getShowPromotionId();

        if (promotionId != 0) {
            PromotionInfo promotionInfo = PromotionMgr.getPromotionInfoById(promotionId);
            if (null != promotionInfo) {
                quality = promotionInfo.getQuality();
                qualification =Long.parseLong(promotionInfo.getDefaultAttribute());
            }
        }
        //技能增加资质
        qualification += getPatronsSkillAddQualification(userPatrons, patronsInfo.getOccupation(), param.getPatronsMap(), param.getCombLeaderDataMap());

        //座骑增加资质
        qualification += getVehicleAddQualification(userPatrons, param.getVehicleMap());

        //美女加资质
//        qualification += getBeautyAddQualification(userPatrons, beautyMap);

        //装扮加资质

        //突破增加资质
        PatronsBreak patronsBreak = PatronsMgr.getPatronsBreak(userPatrons.getBreakLv());
        qualification += patronsBreak.getAddQualification();

     /*   //珍藏阁增加资质
        if(null != userCollectionPavilion) {
            CollectionPavilion collectionPavilion = CollectionMgr.getCollectionPavilion(userCollectionPavilion.getLevel());
            qualification += collectionPavilion.getAddPatronsQualification();
        }*/
        //藏宝系统增加资质
        Map<Integer, Integer> curioSkillCheckMap =new HashMap<>();
        curioSkillCheckMap.put(eSkillType.CurioPatronsQualificationSkill.getValue(), userPatrons.getPatronsId());
        curioSkillCheckMap.put(eSkillType.PeerlessPatronsQualificationAddSkill.getValue(), quality);
        curioSkillCheckMap.put(eSkillType.OccupationPatronsQualificationAddSkill.getValue(), patronsInfo.getOccupation());
        if (isCombLeader(patronsInfo, param.getCombLeaderDataMap())) {
            curioSkillCheckMap.put(eSkillType.CurioSkill334.getValue(), patronsInfo.getCombId());
        }
        qualification += getCurioSkillAdd(userPatrons, param.getCurioSkillDataMap(), curioSkillCheckMap);

        //霓裳秘史增加资质
        qualification += SkinVolumeMgr.getSkillAddition(param.getEmbroideryMeter(), eSkillType.SkinVolumePatronsQualificationAddition.getValue(), patronsInfo.getOccupation());

        //庄园科技加成资质
        qualification += getManorPatronsQualificationAddValue(patronsInfo.getId(), param.getManorTechnologyDataMap());
        //美女走镖技能加资质
        qualification += getBeautyEscortAddQualification(userPatrons, param.getBeautyMap());
        //美女妙音坊技能加资质
        qualification += getBeautyMusicRoomAddQualification(userPatrons, param.getBeautyMap());
        //组合天赋加成
        qualification += getCombTalentAddQualification(userPatrons, param.getUserSkinMap());
        //特定门客资质增加
        qualification += getSpecialPatronsQualificationAddition(userPatrons, param.getUserSkinMap());

        //门客主角时装加资质
        qualification += getPatronsLTPMainRoleSkinAddQualification(userPatrons.getPatronsId(), param.getUserLTPMainRoleSkinMap());

        //美女皮肤技能加固定值
        qualification += getSkinBeautySkillAddAbility(userPatrons, patronsInfo, param.getBeautyMap(),
                eSkillType.SkinBeautySkillAddPatronsAbility.getValue());

        //装备的鱼类加资质
        qualification += FishPondMgr.getFishAddQualification(userPatrons.getPatronsId(), param.getFishDataMap());

        //小助理皮肤套装加门客资质
        qualification += AssistantSkinMgr.getSuitAddition(param.getUserAssistantSuitMap(), eSkillType.SkinVolumePatronsQualificationAddition.getValue(), patronsInfo.getOccupation());

        //厢房加资质
        qualification += getWingRoomAddQualification(patronsInfo.getOccupation(), param.getFurnitureMap(), param.getSuitDataMap());
//        logger.info("userId:{};patronsId:{};qualification:{}", userPatrons.getUserId(), userPatrons.getPatronsId(), qualification);

        //装备的昆虫类加资质
        qualification += CricketMgr.getCricketAddQualification(userPatrons.getPatronsId(), param.getCricketDataMap());

        //门客皮肤羁绊加资质
        qualification += SkinMgr.getPatronsSkinBondAddQualification(userPatrons.getPatronsId(), param.getUserPatronsSkinBondMap(), param.getUserSkinMap());

        //魂石加成
        qualification += getVehicleSoulAddAbility(userPatrons, param.getVehicleMap(), param.getVehicleSoulMap());

        //厢房命盘加资质
        qualification += param.getWingRoomChakraQualificationAddMap().getOrDefault(userPatrons.getPatronsId(), 0L);

        //道具加资质
        qualification += userPatrons.getItemAddQualification();

        //魂骨加资质
        qualification += getVehicleBoneAddQuality(userPatrons, param.getVehicleMap(), param.getVehicleBoneMap());

        //小舞加资质
        qualification += getXiaowuAddQuality(userPatrons, param.getPatronsMap());

        // 旅行册加资质
        qualification += getTravelBookAddQuality(userPatrons, param.getTravelBookBeautyMap(), param.getBeautyMap());

        return qualification;
    }

    /**
     * 旅行册缘分门客赚钱增加资质-卡牌技能
     *
     * @param patron         门客
     * @param beautyAlbumMap 美女旅行册
     * @param beautyMap      美女
     * @return 增加资质
     */
    private static long getTravelBookAddQuality(UserPatrons patron,
                                                Map<Integer, List<UserTravelAlbum>> beautyAlbumMap,
                                                Map<Integer, UserBeauty> beautyMap) {
        long addition = 0;

        for (Map.Entry<Integer, List<UserTravelAlbum>> kv : beautyAlbumMap.entrySet()) {
            int beautyId = kv.getKey();
            UserBeauty beauty = beautyMap.get(beautyId);
            if (beauty == null) {
                continue;
            }
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, patron)) {
                Map<Integer, Integer> albumSkillMap = beauty.getAlbumSkillMap();
                for (Map.Entry<Integer, Integer> kv1 : albumSkillMap.entrySet()) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(kv1.getKey());
                    if (skillInfo == null
                            || skillInfo.getType() != eSkillType.TravelAlbumEarnSpeedQuality.getValue()) {
                        continue;
                    }

                    long tmp = SkillMgr.getSkillAddition(skillInfo, kv1.getValue());
                    addition += tmp;
                }
                for (UserTravelAlbum album : kv.getValue()) {
                    for (UserTravelCard card : album.getCards()) {
                        int cardId = card.getCardId();
                        int cardLevel = card.getLevel();
                        CardConfig cardConfig = TravelBookConfigMgr.getCardInfo(cardId);
                        if (cardConfig == null) {
                            continue;
                        }
                        SkillInfo skillInfo = cardConfig.getSkillInfo();
                        if (skillInfo == null
                                || (skillInfo.getType() != eSkillType.TravelCardEarnSpeedQuality.getValue()
                                && skillInfo.getType() != eSkillType.TravelCardBeautyIntimacy.getValue()
                                && skillInfo.getType() != eSkillType.TravelCardBeautyGlamour.getValue())
                                || card.getPatronId() != patron.getPatronsId()) {
                            continue;
                        }
                        long tmp;
                        if (skillInfo.getType() == eSkillType.TravelCardEarnSpeedQuality.getValue() ) {
                            tmp = SkillMgr.getSkillAddition(skillInfo, cardLevel);
                        } else {
                            tmp = SkillMgr.getSkillAddition(skillInfo, cardLevel, 1);
                        }
                        addition += tmp;
                    }
                }
            }
        }

        return addition;
    }

    /**
     * 小舞的技能给自己和其他门客加资质
     * @param userPatrons
     * @param patronsMap
     * @return
     */
    private static long getXiaowuAddQuality(UserPatrons userPatrons, Map<Integer, UserPatrons> patronsMap) {
        int addition = 0;
        for (UserPatrons patrons : patronsMap.values()) {
            for (UserPatronsSkill skill : patrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                if (skillInfo != null) {
                    //指定门客技能
                    if (skillInfo.getType() == eSkillType.Skill248.getValue() && skillInfo.getParamList().contains(userPatrons.getPatronsId())) {
                        addition += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                    }
                }
            }
        }
        return addition;
    }

    public static long getPatronsLTPMainRoleSkinAddQualification(int patronsId, Map<Integer, UserLTPMainRoleSkin> userLTPMainRoleSkinMap) {
        long addQualification = 0L;
        List<Integer> skinList = SkinMgr.getPatronsLTPMainRoleSkinList(patronsId);
        for (Integer skinId : skinList) {
            UserLTPMainRoleSkin userLTPMainRoleSkin = userLTPMainRoleSkinMap.get(skinId);
            if (userLTPMainRoleSkin != null) {
                addQualification += userLTPMainRoleSkin.getAddQualification();
            }
        }
        return addQualification;
    }

    /**
     * 特定门客主角时装加资质
     */
    private static long getSpecialPatronsQualificationAddition(UserPatrons userPatrons, Map<Integer, UserSkin> userSkinMap) {
        if(null == userPatrons || null == userSkinMap){
            return 0;
        }
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        int addition = 0;
        if(patronsInfo != null){
            //双生皮肤技能需要特殊处理下，先取出双生皮肤，其他皮肤正常算加成，双生皮肤的皮肤等级需要加起来算
            Map<Integer, List<Integer>> twinsSkinMap = getTwinsSkinMap(userSkinMap);
            Map<Integer, UserSkin> tempUserSkinMap = new ConcurrentHashMap<>(userSkinMap);
            for(List<Integer> dataList : twinsSkinMap.values()){
                for(int skinId : dataList){
                    tempUserSkinMap.remove(skinId);
                }
            }
            //非双生皮肤计算加成
            for (UserSkin userSkin : tempUserSkinMap.values()) {
                SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
                if (null != skinInfo) {
                    for (Integer skillId : skinInfo.getSkinEffect()) {
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                        if (null != skillInfo) {
                            if (skillInfo.getType() == eSkillType.SpecialPatronsQualificationAddition.getValue()
                                    && skillInfo.getParamList().get(2) == patronsInfo.getId()) {
                                addition += SkillMgr.getSkillAddition(skillInfo, userSkin.getLevel());
                            }
                        }
                    }
                }
            }
            //双生皮肤计算加成
            for(Map.Entry<Integer, List<Integer>> dataEntry : twinsSkinMap.entrySet()){
                SkinInfo skinInfo = SkinMgr.getSkinInfo(dataEntry.getKey());
                if (null != skinInfo) {
                    for (Integer skillId : skinInfo.getSkinEffect()) {
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                        if (skillInfo != null) {
                            if (skillInfo.getType() == eSkillType.SpecialPatronsQualificationAddition.getValue()
                                    && skillInfo.getParamList().get(2) == patronsInfo.getId()) {
                                int skinLv = 0;
                                for(int skinId : dataEntry.getValue()){
                                    UserSkin userSkin = userSkinMap.get(skinId);
                                    if(null != userSkin){
                                        skinLv += userSkin.getLevel();
                                    }
                                }
                                addition += SkillMgr.getSkillAddition(skillInfo, skinLv);
                            }
                        }
                    }
                }
            }
        }
        return addition;
    }


    /**
     * 特定门客主角时装加赚钱千分比
     */
    private static long getSpecialPatronsEarnAddition(UserPatrons userPatrons, Map<Integer, UserSkin> userSkinMap, int quality) {
        if(null == userPatrons || null == userSkinMap){
            return 0;
        }

        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        int addition = 0;
        if(patronsInfo != null){
            //双生皮肤技能需要特殊处理下，先取出双生皮肤，其他皮肤正常算加成，双生皮肤的皮肤等级需要加起来算
            Map<Integer, List<Integer>> twinsSkinMap = getTwinsSkinMap(userSkinMap);
            Map<Integer, UserSkin> tempUserSkinMap = new ConcurrentHashMap<>(userSkinMap);
            for(List<Integer> dataList : twinsSkinMap.values()){
                for(int skinId : dataList){
                    tempUserSkinMap.remove(skinId);
                }
            }
            //非双生皮肤计算加成
            for (UserSkin userSkin : tempUserSkinMap.values()) {
                SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
                if (null != skinInfo) {
                    for (Integer skillId : skinInfo.getSkinEffect()) {
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                        if (null != skillInfo) {
                            // 参数：赚钱千分比|指定门客|指定职业|指定门客品质
                            // 参数2：-1表示所有，0表示不指定，门客id表示指定；参数3：-1表示所有职业，0表示无，1.2.3.4.5对应士农工商侠；参数4：0表示无，1.2.3.4.5表示品质
                            // 需要三个条件同时满足
                            if (skillInfo.getType() == eSkillType.SpecialPatronsEarnAddition.getValue()) {
                                if (skillInfo.getParamList().get(1) != 0 && skillInfo.getParamList().get(1) != patronsInfo.getId()) {
                                    continue;
                                }
                                if (skillInfo.getParamList().get(2) != 0 && skillInfo.getParamList().get(2) != patronsInfo.getOccupation()) {
                                    continue;
                                }
                                // 判断当前是否是无双  是否有晋升无双
                                if (skillInfo.getParamList().get(3) != 0 && skillInfo.getParamList().get(3) != quality) {
                                    continue;
                                }
                                addition += SkillMgr.getSkillAddition(skillInfo, userSkin.getLevel());
                            }
                        }
                    }
                }
            }
            //双生皮肤计算加成
            for(Map.Entry<Integer, List<Integer>> dataEntry : twinsSkinMap.entrySet()){
                SkinInfo skinInfo = SkinMgr.getSkinInfo(dataEntry.getKey());
                if (null != skinInfo) {
                    for (Integer skillId : skinInfo.getSkinEffect()) {
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                        if (skillInfo != null) {
                            if (skillInfo.getType() == eSkillType.SpecialPatronsEarnAddition.getValue()) {
                                if (skillInfo.getParamList().get(1) != 0 && skillInfo.getParamList().get(1) != patronsInfo.getId()) {
                                    continue;
                                }
                                if (skillInfo.getParamList().get(2) != 0 && skillInfo.getParamList().get(2) != patronsInfo.getOccupation()) {
                                    continue;
                                }
                                // 判断当前是否是无双 是否有晋升无双
                                if (skillInfo.getParamList().get(3) != 0 && skillInfo.getParamList().get(3) != quality) {
                                    continue;
                                }
                                int skinLv = 0;
                                for(int skinId : dataEntry.getValue()){
                                    UserSkin userSkin = userSkinMap.get(skinId);
                                    if(null != userSkin){
                                        skinLv += userSkin.getLevel();
                                    }
                                }
                                addition += SkillMgr.getSkillAddition(skillInfo, skinLv);
                            }
                        }
                    }
                }
            }
        }
        return addition;
    }

    private static long getCombTalentAddQualification(UserPatrons userPatrons, Map<Integer, UserSkin> userSkinMap) {
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        int combId = patronsInfo.getCombId();
        int addition = 0;
        //双生皮肤技能需要特殊处理下，先取出双生皮肤，其他皮肤正常算加成，双生皮肤的皮肤等级需要加起来算
        Map<Integer, List<Integer>> twinsSkinMap = getTwinsSkinMap(userSkinMap);
        Map<Integer, UserSkin> tempUserSkinMap = new ConcurrentHashMap<>(userSkinMap);
        for(List<Integer> dataList : twinsSkinMap.values()){
            for(int skinId : dataList){
                tempUserSkinMap.remove(skinId);
            }
        }
        //非双生皮肤计算加成
        for (UserSkin userSkin : tempUserSkinMap.values()) {
            SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
            if (null != skinInfo) {
                for (Integer skillId : skinInfo.getSkinEffect()) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (null != skillInfo) {
                        if (skillInfo.getType() == eSkillType.CombPatronsQualificationAddition.getValue()
                                && skillInfo.getParamList().get(2) == combId) {
                            addition += SkillMgr.getSkillAddition(skillInfo, userSkin.getLevel());
                        }
                    }
                }
            }
        }
        //双生皮肤计算加成
        for(Map.Entry<Integer, List<Integer>> dataEntry : twinsSkinMap.entrySet()){
            SkinInfo skinInfo = SkinMgr.getSkinInfo(dataEntry.getKey());
            if (null != skinInfo) {
                for (Integer skillId : skinInfo.getSkinEffect()) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (skillInfo != null) {
                        if (skillInfo.getType() == eSkillType.CombPatronsQualificationAddition.getValue()
                                && skillInfo.getParamList().get(2) == combId) {
                            int skinLv = 0;
                            for(int skinId : dataEntry.getValue()){
                                UserSkin userSkin = userSkinMap.get(skinId);
                                if(null != userSkin){
                                    skinLv += userSkin.getLevel();
                                }
                            }
                            addition += SkillMgr.getSkillAddition(skillInfo, skinLv);
                        }
                    }
                }
            }
        }

        return addition;
    }

    /**
     * 座骑增加资质
     */
    private static long getBeautyAddQualification(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long qualification = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                qualification += BeautyMgr.getBeautyQualification(beauty);
            }
        }
        return qualification;
    }

    /**
     * 增加门客能力的技能加成
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    private static double getAddPatronsAbilityAddition(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap, Map<Integer, UserPatrons> patronsMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        //美名类的加成
        double addition = SkillMgr.getIdentitySkillAddition(beautyMap, eSkillType.AddPatronsAbility.getValue(), userPatrons.getPatronsId());
        //天赋类的加成
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        addition += SkillMgr.getTalentSkillAddition(patronsMap, eSkillType.AddPatronsAbilityByOccupation.getValue(), patronsInfo.getOccupation());
        addition += getAdvanceSkillAddRatio(userPatrons, patronsMap);
        addition += getCricketSkillAddRatio(userPatrons);
        addition += getCricketFateAddRatio(userPatrons);
        return addition;
    }

    /**
     * 进阶技能 特定门客千分比加成
     * @param userPatrons
     * @param patronsMap
     * @return
     */
    public static long getAdvanceSkillAddRatio(UserPatrons userPatrons, Map<Integer, UserPatrons> patronsMap) {
        long addRatio = 0;
        PatronsInfo patronsInfo = getPatronsInfo(userPatrons.getPatronsId());
        if (patronsInfo != null) {
            for (UserPatrons patrons : patronsMap.values()) {
                List<UserPatronsSkill> skillList = patrons.getSkillList();
                for (UserPatronsSkill skill : skillList) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skill.getSkillId());
                    if (skillInfo != null) {
                        if (skillInfo.getType() == eSkillType.SpecialOccupationPatronsAbilityAddRatio.getValue()
                                && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == patronsInfo.getOccupation())) {
                            addRatio += SkillMgr.getSkillAddition(skillInfo, skill.getSkillLv());
                        }
                    }
                }
            }
        }
        return addRatio;
    }


    /**
     * 美女增加的缘分百分比加成
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    public static long getBeautyAddPercentage(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long percentage = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                int level = beauty.getSkill2();
                List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillList.get(1));
                long addPercentage = SkillMgr.getSkillAddition(skillInfo, level);
                percentage += addPercentage;


            }
        }

        long musicRoomAdd = getBeautyMusicRoomAddPercentage(userPatrons, beautyMap);
        percentage += musicRoomAdd;

        return percentage;
    }

    /**
     * 美女门客技能增加固定值
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    public static long getBeautyAddRegular(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                int level = beauty.getSkill1();
                List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillList.get(0));
                long addregular = SkillMgr.getSkillAddition(skillInfo, level);
                regular += addregular;
            }
        }
        return regular;
    }

    /**
     * 美女走镖门客技能增加赚钱固定值
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    private static long getBeautyEscortAddRegular(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                int level = beauty.getEscortSkill1();
                List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillList.get(0));
                long addregular = SkillMgr.getSkillAddition(skillInfo, level);
                regular += addregular;
            }
        }
        return regular;
    }

    /**
     * 美女走镖门客技能增加资质固定值
     */
    private static long getBeautyEscortAddQualification(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                int level = beauty.getEscortSkill2();
                List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillList.get(1));
                long addregular = SkillMgr.getSkillAddition(skillInfo, level);
                regular += addregular;
            }
        }
        return regular;
    }

    /**
     * 座骑增加资质
     */
    private static long getVehicleAddQualification(UserPatrons userPatrons, Map<String, UserVehicle> vehicleMap) {
        if(null == userPatrons || null == vehicleMap){
            return 0;
        }
        long qualification = 0;
        for (UserVehicle vehicle : vehicleMap.values()) {
            if (vehicle.getPatronsId() == userPatrons.getPatronsId() && !vehicle.isDelete()) {
                qualification += VehicleMgr.getVehicleQualification(vehicle.getTemplateId(), vehicle.getLevel());
                break;
            }
        }
        return qualification;
    }

    public static boolean isCombLeader(PatronsInfo patronsInfo, Map<Integer, UserCombLeaderData> combLeaderDataMap) {
        boolean isLeader = false;
        UserCombLeaderData combLeaderData = combLeaderDataMap.get(patronsInfo.getCombId());
        if (combLeaderData != null && combLeaderData.getLeaderId() == patronsInfo.getId()) {
            isLeader = true;
        }
        return isLeader;
    }

    /**
     * 门客技能增加资质
     */
    private static long getPatronsSkillAddQualification(UserPatrons userPatrons, int occupation, Map<Integer, UserPatrons> patronsMap, Map<Integer, UserCombLeaderData> combLeaderDataMap) {
        if (null == userPatrons) {
            return 0;
        }
        long qualification = 0;
        if (null != userPatrons.getSkillList()) {
            for (UserPatronsSkill patronsSkill : userPatrons.getSkillList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                if (null == skillInfo) {
                    continue;
                }
                if (eSkillType.Qualification.getValue() == skillInfo.getType()) {
                    qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
                if (eSkillType.XiaoXiongPatronHalo.getValue() == skillInfo.getType()) {
                    qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
                if (eSkillType.StrangePatronHalo.getValue() == skillInfo.getType()) {
                    qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
                if (eSkillType.PatronsKeepSakeLinkAddtition.getValue() == skillInfo.getType()) {//信物技能加自身资质
                    qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
                if (eSkillType.ZhangQiLingSkill.getValue() == skillInfo.getType()) {//盗墓笔记 技能
                    List<Integer> skillList = StringUtils.stringToIntegerList(GameConfig.PATRONS_ZHANGQILING_EX_SKILLS, "\\|");
                    int idx = skillList.indexOf(patronsSkill.getSkillId());
                    if(idx > 0) {
                        int preSkillId = skillList.get(idx - 1);
                        SkillInfo preSkinInfo = SkillMgr.getSkillInfo(preSkillId);
                        UserPatronsSkill prePatronsSkill = userPatrons.getPatronsSkill(preSkillId);
                        if (preSkinInfo != null && prePatronsSkill != null && preSkinInfo.getMaxLevel() > prePatronsSkill.getTotalSkillLevel()) {
                            continue;
                        }
                    }
                    qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                }
            }
        }

        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());

        boolean isLeader = isCombLeader(patronsInfo, combLeaderDataMap);

        for (UserPatrons tempPatrons : patronsMap.values()) {
            if (null != tempPatrons.getSkillList()) {
                for (UserPatronsSkill patronsSkill : tempPatrons.getSkillList()) {
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(patronsSkill.getSkillId());
                    if (null == skillInfo) {
                        continue;
                    }
                    if (eSkillType.SkinPatronsSkillAddPatronsQualification.getValue() == skillInfo.getType()) {//特定职业门客加资质
                        int param3 = skillInfo.getParamList().get(2);
                        if(0 == param3 || occupation == param3){
                            qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getSkillLv());
                        }
                    }
                    //羁绊技能增加资质
                    if (eSkillType.PatronsNewCombSkill.getValue() == skillInfo.getType()) {
                        int combId = skillInfo.getParamList().get(2);
                        if (0 != combId && patronsInfo.getCombId() == combId) {
                            qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                        }
                    }

                    //被信物羁绊后加资质
                    if (eSkillType.PatronsKeepSakeLinkAddtition.getValue() == skillInfo.getType()) {
                        if (tempPatrons.getShowKeepSakePatronsId() == userPatrons.getPatronsId()) {
                            qualification += SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                        }
                    }

                    if (eSkillType.CombLeaderSkill208.getValue() == skillInfo.getType() && isLeader) {//给组合首领加资质,如果是首领的技能翻倍加
                        int addition = SkillMgr.getSkillAddition(skillInfo, patronsSkill.getTotalSkillLevel());
                        if (tempPatrons.getPatronsId() == userPatrons.getPatronsId()) {//参数2是千分比
                            int multiAddition = BigDecimal.valueOf(addition).multiply(BigDecimal.valueOf(skillInfo.getParamList().get(1)).divide(BigDecimal.valueOf(1000))).setScale(0, BigDecimal.ROUND_UP).intValue();
                            qualification += multiAddition;
                        }else {
                            qualification += addition;
                        }
                    }
                }
            }
        }
        return qualification;
    }
    //把json字符串门客信息转换成id列表
    public static List<Integer> parsePatronInfoStrToIdList(String patronInfoStr){
        List<UserPatrons> patronsList = JSON.parseArray(patronInfoStr,UserPatrons.class);
        List<Integer> patronIdList = new ArrayList<>();
        if(null != patronsList){
            for(UserPatrons userPatrons : patronsList){
                if(!patronIdList.contains(userPatrons.getPatronsId())){
                    patronIdList.add(userPatrons.getPatronsId());
                }
            }
        }
        return patronIdList;
    }

    /**
     * 初始化门客技能
     * @param isDelete 0为未删除，1为删除
     * @return
     */
    public static UserPatronsSkill initUserPatronsSkill(UserPatrons userPatrons, int skillId, int type, int skillLv,int isDelete) {
        UserPatronsSkill patronsSkill = new UserPatronsSkill();
        patronsSkill.setUserId(userPatrons.getUserId());
        patronsSkill.setPatronsId(userPatrons.getPatronsId());
        patronsSkill.setSkillId(skillId);
        patronsSkill.setSkillLv(skillLv);
        patronsSkill.setType(type);
        patronsSkill.setSkinSkillLevel(0);
        String extraParams = "";
        if (type == ePatronsSkillType.Cricket.getValue()) {
            // 蛐蛐技能默认激活时突破次数为1
            extraParams = "1";
        }
        patronsSkill.setExtraParams(extraParams);
        patronsSkill.setIsDelete(isDelete);
        patronsSkill.setInsertOption();
        return patronsSkill;
    }

    /**
     * 按能力从大到小排序
     * @param rank
     * @param userPatronsList
     * @return
     */
    public static UserPatrons getUserPatronsByEarnSpeedRank(int rank, List<UserPatrons> userPatronsList) {
        UserPatrons patrons = null;
        userPatronsList.sort((o1, o2) -> {
            BigInteger a1 = o1.getAbility();
            BigInteger a2 = o2.getAbility();
            return a2.compareTo(a1);
        });
        if (userPatronsList.size() >= rank) {
            patrons = userPatronsList.get(rank - 1);
        } else if (userPatronsList.isEmpty()) {

        } else {
            patrons = userPatronsList.get(userPatronsList.size() - 1);
        }
        return patrons;
    }

    /**
     * 等级上限加成
     * @param patronsId
     * @param embroideryMeter
     * @return
     */
    public static int getSkillAddLevel(int patronsId, int embroideryMeter) {
        int addLv = 0;
        PatronsInfo patronsInfo = patronsInfoMap.get(patronsId);
        if (patronsInfo == null) {
            return addLv;
        }
        addLv += SkinVolumeMgr.getSkillAddition(embroideryMeter, eSkillType.SkinVolumePatronsLvLimitAddition.getValue(), patronsInfo.getOccupation());
        return addLv;
    }

    public static int getPatronsMaxBreakLv() {
        int maxBreakLv = 0;
        for (PatronsBreak patronsBreak : patronsBreakMap.values()) {
            if (patronsBreak.getCurrentMaxLv() == GameConfig.PATRONS_UPGRADE_MAX_LEVEL) {
                maxBreakLv = patronsBreak.getBreakLv();
            }
        }
        return maxBreakLv;
    }

    public static int getCurMaxLevel(int breakLv, int patronsId, int embroideryMeter) {
        int breakMaxLevel = patronsBreakMap.get(breakLv).getCurrentMaxLv();
        if (breakLv <= getPatronsMaxBreakLv()) {
            return breakMaxLevel;
        }
        return GameConfig.PATRONS_UPGRADE_MAX_LEVEL + getSkillAddLevel(patronsId, embroideryMeter);
    }

    public static String getUserPatronsDetailInfoJsonStr(long userId, int patronsId) {
        return parsePatronsDetailInfoJsonStr(userId, patronsId);
    }


    public static String parsePatronsDetailInfoJsonStr(long userId, int patronsId) {
        CalcPatronsAbilityParam calcPatronsAbilityParam = buildCalcPatronsAbilityParam(userId, patronsId);
        Map<Integer, UserPatrons> userPatronsMap = calcPatronsAbilityParam.getPatronsMap();
        UserPatrons userPatrons = userPatronsMap.get(patronsId);
        Map<String, UserVehicle> userVehicleMap = calcPatronsAbilityParam.getVehicleMap();
        Map<Integer, UserVehicleSoul> userVehicleSoulMap = calcPatronsAbilityParam.getVehicleSoulMap();
        Map<Integer, UserCurioSkillData> curioSkillDataMap = calcPatronsAbilityParam.getCurioSkillDataMap();
        Map<Integer, UserVehicleBone> boneMap = calcPatronsAbilityParam.getVehicleBoneMap();
        Map<Integer, UserBeauty> beautyMap = calcPatronsAbilityParam.getBeautyMap();
        Map<Integer, ManorTechnologyData> technologyDataMap = calcPatronsAbilityParam.getManorTechnologyDataMap();
        Map<Integer, FishData> fishDataMap = calcPatronsAbilityParam.getFishDataMap();
        Map<Integer, CricketData> cricketDataMap = calcPatronsAbilityParam.getCricketDataMap();
        Map<Integer, List<UserTravelAlbum>> beautyAlbumMap = calcPatronsAbilityParam.getTravelBookBeautyMap();

        PatronsInfo patronsInfo = getPatronsInfo(patronsId);

        JSONObject jsonObject = new JSONObject();
        try {
            if (userPatrons != null) {
                jsonObject.put("patronsId", userPatrons.getPatronsId());
                jsonObject.put("value", userPatrons.getAbility());
                jsonObject.put("patronsLv", userPatrons.getLevel());
                jsonObject.put("stageLv", userPatrons.getStageLv());
                jsonObject.put("qualification", userPatrons.getTotalQualification());
                jsonObject.put("skinId", userPatrons.getSkinId());
                jsonObject.put("promotionId", userPatrons.getShowPromotionId());
                jsonObject.put("keepSakePatronsId", userPatrons.getShowKeepSakePatronsId());
                JSONArray skillList = new JSONArray();
                for (UserPatronsSkill skill : userPatrons.getSkillList()) {
                    JSONObject skillJson = new JSONObject();
                    skillJson.put("skillId", skill.getSkillId());
                    skillJson.put("skillLv", skill.getSkillLv());
                    skillJson.put("type", skill.getType());
                    skillJson.put("skinSkillLevel", skill.getSkinSkillLevel());
                    skillJson.put("totalSkillLevel", skill.getTotalSkillLevel());
                    skillList.add(skillJson);
                }
                jsonObject.put("skillList", skillList);
                int occupation = getPatronsInfo(userPatrons.getPatronsId()).getOccupation();
                for (UserVehicle userVehicle : userVehicleMap.values()) {
                    if (userVehicle.getPatronsId() == userPatrons.getPatronsId()) {
                        JSONObject vehicleJson = new JSONObject();
                        vehicleJson.put("vehicleId", userVehicle.getTemplateId());
                        vehicleJson.put("vehicleLv", userVehicle.getLevel());
                        Map<String, UserVehicle> tempUserVehicleMap = new ConcurrentHashMap<>();
                        tempUserVehicleMap.put(userVehicle.getVehicleUid(), userVehicle);
                        long addValue = getVehicleSoulAddAbility(userPatrons, tempUserVehicleMap, userVehicleSoulMap);
                        vehicleJson.put("vehicleQualification", VehicleMgr.getVehicleQualification(userVehicle.getTemplateId(), userVehicle.getLevel()) + addValue);
                        vehicleJson.put("vehicleStudyLv", userVehicle.getStudyLv());
                        long rightSkillSize = userVehicle.getSkillMapEffect().values().stream().filter(skill -> skill.getSkillType() == occupation).count();
                        vehicleJson.put("vehicleSkillSize", rightSkillSize);

                        int curioAddition = (int) getCurioSkillAdd(userPatrons, curioSkillDataMap, eSkillType.OccupationSoulStoneAddSkill.getValue(), occupation);
                        double vehicleAddition = PatronsMgr.getVehicleAddition(userPatrons, userVehicleMap, userVehicleSoulMap, curioAddition, boneMap);
                        vehicleJson.put("vehicleAddition", vehicleAddition);

                        //兽魂的数据
                        List<JSONObject> soulList = new ArrayList<>();
                        for (UserVehicleSoul userVehicleSoul : userVehicleSoulMap.values()) {
                            if (userVehicleSoul.getVehicleId().equals(userVehicle.getVehicleUid())) {
                                JSONObject soulData = new JSONObject();
                                soulData.put("soulId", userVehicleSoul.getSoulId());
                                soulData.put("id", userVehicleSoul.getConfigId());
                                soulData.put("occs", userVehicleSoul.getOccList());

                                List<JSONObject> entrys = new ArrayList<>();
                                if (userVehicleSoul.getEntryMap().size() > 0) {
                                    for (int index = 0; index < userVehicleSoul.getEntryMap().size(); index++) {
                                        if (userVehicleSoul.getEntryMap().containsKey(index)) {
                                            List<Integer> infoList = userVehicleSoul.getEntryMap().get(index);
                                            JSONObject entry = new JSONObject();
                                            entry.put("occ", infoList.get(1));
                                            entry.put("value", infoList.get(2));
                                            entry.put("washTime", infoList.get(3));

                                            entrys.add(entry);
                                        } else {
                                            break;
                                        }
                                    }
                                }
                                soulData.put("entrys", entrys);

                                JSONObject equip = new JSONObject();

                                equip.put("equipTime", userVehicleSoul.getEquipTime());
                                equip.put("pos", userVehicleSoul.getEquipPos());
                                equip.put("vehicleId", userVehicleSoul.getVehicleId());

                                soulData.put("equip", equip);

                                soulList.add(soulData);
                            }
                        }
                        vehicleJson.put("soulList", soulList);
                        //魂骨
                        vehicleJson.put("boneLv", userVehicle.getBoneLv());
                        vehicleJson.put("boneHole", userVehicle.getBoneHole());
                        List<JSONObject> boneList = new ArrayList<>();
                        for (UserVehicleBone userVehicleBone : boneMap.values()) {
                            if (userVehicleBone.getVehicleId().equals(userVehicle.getVehicleUid())) {
                                JSONObject boneJson = new JSONObject();
                                boneJson.put("configId", userVehicleBone.getConfigId());
                                boneJson.put("pos", userVehicleBone.getEquipPos());
                                List<JSONObject> boneSkillList = new ArrayList<>();
                                for (Map.Entry<Integer, Integer> entry : userVehicleBone.getSkillMap().entrySet()) {
                                    JSONObject boneSkillJson = new JSONObject();
                                    boneSkillJson.put("skillId", entry.getKey());
                                    boneSkillJson.put("skillLv", entry.getValue());
                                    boneSkillList.add(boneSkillJson);
                                }
                                boneJson.put("skill", boneSkillList);
                                boneList.add(boneJson);
                            }
                        }
                        vehicleJson.put("boneList", boneList);

                        jsonObject.put("soulBlockList", userVehicle.getSoulBlockList());

                        jsonObject.put("vehicle", vehicleJson);
//                        jsonObject.put("vehicleSoul", userVehicleSoulMap);
                        break;
                    }
                }

                PatronsAbilityCalcBaseParams patronsAbilityCalcBaseParams = calcPatronsAbilityCalcBaseParams(userPatrons, calcPatronsAbilityParam);
                int quality = patronsAbilityCalcBaseParams.getQuality();
                BigDecimal abilityAdditionRatio = patronsAbilityCalcBaseParams.getAbilityAdditionRatio();
                BigDecimal calcAbilityParam = patronsAbilityCalcBaseParams.getCalcAbilityParam();
                BigDecimal baseAbility = patronsAbilityCalcBaseParams.calcBaseAbility();

                BigDecimal k8 = BigDecimal.valueOf((double) FishPondMgr.getFishAddPercentage(patronsInfo.getId(), calcPatronsAbilityParam.getFishDataMap()) / 1000).setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

                JSONArray beautyJsonList = new JSONArray();
                for (UserBeauty beauty : beautyMap.values()) {
                    if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                        JSONObject beautyJson = new JSONObject();
                        int level1 = beauty.getSkill1();
                        List<Integer> beautySkillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_PATRONS_SKILL, "\\|");
                        SkillInfo skillInfo1 = SkillMgr.getSkillInfo(beautySkillList.get(0));
                        BigDecimal skillAddition1 = BigDecimal.valueOf(SkillMgr.getSkillAddition(skillInfo1, level1));
                        int level2 = beauty.getSkill2();
                        SkillInfo skillInfo2 = SkillMgr.getSkillInfo(beautySkillList.get(1));
                        BigDecimal skillAddition2 = BigDecimal.valueOf((double) SkillMgr.getSkillAddition(skillInfo2, level2) / 1000)
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP)
                                .multiply(baseAbility)
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

                        int escortSkillLevel1 = beauty.getEscortSkill1();
                        List<Integer> escortSkill1 = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                        SkillInfo skillInfo = SkillMgr.getSkillInfo(escortSkill1.get(0));
                        BigDecimal escortSkill1Addition = BigDecimal.valueOf(SkillMgr.getSkillAddition(skillInfo, escortSkillLevel1));


                        int escortSkillLevel2 = beauty.getEscortSkill2();
                        List<Integer> escortSkill2 = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                        SkillInfo escortSkill2Info2 = SkillMgr.getSkillInfo(escortSkill2.get(1));
                        BigDecimal escortSkill2Addition = BigDecimal.valueOf(SkillMgr.getSkillAddition(escortSkill2Info2, escortSkillLevel2))
                                .multiply(calcAbilityParam)
                                .multiply(BigDecimal.ONE.add(abilityAdditionRatio))
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                        BigDecimal totalAddition = skillAddition1.add(skillAddition2).add(escortSkill1Addition).add(escortSkill2Addition);

                        //妙音坊技能
                        BigDecimal musicRoomAddition = BigDecimal.ZERO;
                        for (Map.Entry<Integer, BigInteger> entry : beauty.getMusicRoomSkill().getGoods().entrySet()) {
                            int skillId = entry.getKey();
                            int skillLv = entry.getValue().intValue();
                            SkillInfo musicRoomSkillInfo = SkillMgr.getSkillInfo(skillId);
                            if (musicRoomSkillInfo == null) {
                                continue;
                            }
                            int skillAddition = SkillMgr.getSkillAddition(musicRoomSkillInfo, skillLv);
                            if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsEscortSkill1.getValue()){
                                //加固定值
                                musicRoomAddition = musicRoomAddition.add(BigDecimal.valueOf(skillAddition));
                            } else if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsSkill2.getValue()){
                                //加百分比
                                BigDecimal newAddition = BigDecimal.valueOf((double) skillAddition / 1000)
                                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP)
                                        .multiply(baseAbility)
                                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                                musicRoomAddition = musicRoomAddition.add(newAddition);
                            } else if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsEscortSkill2.getValue()){
                                //加资质
                                BigDecimal newAddition = BigDecimal.valueOf(skillAddition)
                                        .multiply(calcAbilityParam)
                                        .multiply(BigDecimal.ONE.add(abilityAdditionRatio))
                                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                                musicRoomAddition = musicRoomAddition.add(newAddition);
                            }
                        }
                        totalAddition = totalAddition.add(musicRoomAddition);

                        BigDecimal additionByPeerlessSkill = BeautyMgr.getBeautyPeerlessSkillAddition(totalAddition,
                                beauty, userPatrons);
//                        totalAddition = totalAddition.add(additionByPeerlessSkill);

                        totalAddition = totalAddition.setScale(0, RoundingMode.UP);
                        beautyJson.put("beautyId", beauty.getBeautyId());
                        beautyJson.put("beautyAddition", totalAddition.toString());
                        beautyJson.put("peerlessAddition", additionByPeerlessSkill.toString());
                        beautyJson.put("peerlessUp", beauty.getPeerlessUp());
                        beautyJsonList.add(beautyJson);
                    }
                }
                jsonObject.put("beautyList", beautyJsonList);

                //契约美女
                JSONArray contractBeautyList = new JSONArray();
                for (UserPatronsContract patronsContract : userPatrons.getPatronsContractMap().values()) {
                    JSONObject contractJson = new JSONObject();
                    contractJson.put("beautyId", patronsContract.getBeautyId());
                    contractJson.put("pos", patronsContract.getPos());
                    contractJson.put("abilityAdd", patronsContract.getAbilityAdd());
                    contractBeautyList.add(contractJson);
                }
                jsonObject.put("contractBeautyList", contractBeautyList);

                JSONArray manorSkillList = new JSONArray();
                for (ManorTechnologyData technologyData : technologyDataMap.values()) {
                    ManorTechnologyConfig manorTechnologyConfig = ManorMgr.getManorTechnologyConfigMap().get(technologyData.getId());
                    if (manorTechnologyConfig != null) {
                        JSONObject manorJson = new JSONObject();
                        long manorAddition = 0L;
                        int pos = 0;
                        for (Integer skillId : manorTechnologyConfig.getVolumesIdList()) {
                            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                            if (skillInfo != null) {
                                if (skillInfo.getType() == eSkillType.ManorPatronsAbilityAddValue.getValue()) {
                                    String objStr = manorTechnologyConfig.getVolumeObjList().get(pos);
                                    String[] objArr = objStr.split(";");
                                    for (String obj : objArr) {
                                        if (Integer.parseInt(obj) == userPatrons.getPatronsId()) {
                                            if (technologyData.getSkillLvList().size() - 1 >= pos) {
                                                manorAddition += SkillMgr.getSkillAddition(skillInfo, technologyData.getSkillLvList().get(pos));
                                            }
                                        }
                                    }
                                } else if (skillInfo.getType() == eSkillType.ManorPatronsQualificationAddValue.getValue()) {
                                    String objStr = manorTechnologyConfig.getVolumeObjList().get(pos);
                                    String[] objArr = objStr.split(";");
                                    for (String obj : objArr) {
                                        if (Integer.parseInt(obj) == userPatrons.getPatronsId()) {
                                            if (technologyData.getSkillLvList().size() - 1 >= pos) {
                                                long addQualification = SkillMgr.getSkillAddition(skillInfo, technologyData.getSkillLvList().get(pos));
                                                manorAddition += BigDecimal.valueOf(addQualification).multiply(userPatrons.getCalcAbilityParam()).multiply(BigDecimal.ONE.add(userPatrons.getAbilityAdditionRatio())).setScale(0, BigDecimal.ROUND_UP).longValue();
                                            }
                                        }
                                    }
                                }
                            }
                            pos++;
                        }
                        if (manorAddition > 0) {
                            manorJson.put("manorTechnologyId", manorTechnologyConfig.getId());
                            manorJson.put("manorAddition", manorAddition);
                            manorSkillList.add(manorJson);
                        }
                    }
                }
                jsonObject.put("manorSkillList", manorSkillList);

                JSONObject fishJson = new JSONObject();
                //鱼类加成
                long fishQualification = FishPondMgr.getFishAddQualification(userPatrons.getPatronsId(), fishDataMap);
                long fishAddAbility = BigInteger.valueOf(FishPondMgr.getFishAbilityAddValue(patronsInfo.getId(), fishDataMap)).longValue();
                FishData fishData = FishPondMgr.getUserFishByPatrons(userPatrons.getPatronsId(), fishDataMap);
                if (fishData != null) {
                    fishJson.put("fishId", fishData.getFishId());
                    fishJson.put("fishLv", fishData.getLv());
                    fishJson.put("fishQualification", fishQualification);
                    fishJson.put("fishAddAbility", fishAddAbility);
                    fishJson.put("fishAddPercentage", k8);
                    fishJson.put("fishSkillNum", fishData.getFishSkillDataMap().size());
                    jsonObject.put("fishData", fishJson);
                }
                JSONObject cricketJson = new JSONObject();
                long cricketQualification = CricketMgr.getCricketAddQualification(userPatrons.getPatronsId(), cricketDataMap);
                CricketData cricketData = CricketMgr.getUserCricketByPatrons(userPatrons.getPatronsId(), cricketDataMap);
                if (cricketData != null) {
                    cricketJson.put("cricketId", cricketData.getCricketId());
                    cricketJson.put("titleId", cricketData.getTitle());
                    cricketJson.put("littleTitle", cricketData.getLittleTitle());
                    cricketJson.put("quality", cricketData.getQuality());
                    if(cricketData.getEquipSkillList().size() > 0){
                        cricketJson.put("skillLv", cricketData.getEquipSkillList().get(0).getLv());//技能等级
                    }else{
                        cricketJson.put("skillLv", 1);//技能等级
                    }
                    cricketJson.put("cricketAddQualification", cricketQualification);//技能加的资质
                    jsonObject.put("cricketData", cricketJson);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return jsonObject.toString();
    }


    /**
     * 获取某个作用所有门客的技能加成值
     * @param player
     */
    public static int getMonopolyMarketPatronsPlus(GamePlayer player, int type){
        int addAttackPlus = 0;
        for (UserPatrons item : player.getModule(PatronsModule.class).getUserPatronsMap().values()){
            for (UserPatronsSkill userPatronsSkill : item.getSkillList()){
                SkillInfo skillInfo = SkillMgr.getSkillInfo(userPatronsSkill.getSkillId());
                if (skillInfo.getType() == type) {
                    addAttackPlus += SkillMgr.getSkillAddition(skillInfo, userPatronsSkill.getSkillLv());
                }
            }
        }
        return addAttackPlus;
    }


    /**
     * 这些门客中，是否拥有这个技能
     * @param patronsIdList
     * @param type
     * @return
     */
    public static boolean hasSkillType(GamePlayer player,List<Integer> patronsIdList,int type){
        List<UserPatrons> list = new ArrayList<>();
        for (Integer item : patronsIdList){
            UserPatrons patrons = player.getModule(PatronsModule.class).getUserPatrons(item);
            if(patrons != null){
                list.add(patrons);
            }
        }
        return hasSkillType(list,type);
    }

    /**
     * 这些门客中，是否拥有这个技能
     * @param patronsList
     * @param type
     * @return
     */
    public static boolean hasSkillType(List<UserPatrons> patronsList,int type){
        for (UserPatrons item : patronsList){
            for (UserPatronsSkill userPatronsSkill : item.getSkillList()){
                SkillInfo skillInfo = SkillMgr.getSkillInfo(userPatronsSkill.getSkillId());
                if (skillInfo.getType() == type) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 是否是精进技能
     * @param skillId
     * @return
     */
    public static boolean isStageSkill(int skillId) {
        for (PatronsStage patronsStage : patronsStageMap.values()) {
            if (patronsStage.getAddSkillId() == skillId) {
                return true;
            }
        }
        return false;
    }

    /**
     * 美女皮肤技能增加固定值
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    private static long getSkinBeautySkillAddAbility(UserPatrons userPatrons, PatronsInfo patronsInfo, Map<Integer, UserBeauty> beautyMap, int skillType) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long addition = 0;
        for (UserBeauty userBeauty : beautyMap.values()) {
            BeautyInfo beautyInfo = BeautyMgr.getBeautyInfo(userBeauty.getBeautyId());
            int skillIndex = 0;
            for(int skillId : beautyInfo.getHaloSkillList()){
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if(null == skillInfo){
                    skillIndex++;
                    continue;
                }
                if(skillInfo.getType() == skillType){//加固定值或者千分比的技能
                    int param3 = skillInfo.getParamList().get(2);
                    if(0 == param3 || patronsInfo.getOccupation() == param3){//给特定职位门客加固定值
                        if(0 == skillIndex) {
                            addition += SkillMgr.getSkillAddition(skillInfo, userBeauty.getSkinSkill1());
                        }else if(1 == skillIndex){
                            addition += SkillMgr.getSkillAddition(skillInfo, userBeauty.getSkinSkill2());
                        }
                    }
                }
                skillIndex++;
            }
        }
        return addition;
    }

    /**
     * 获取孙子职业技能增加能力
     * @param occupation
     * @param grandChildProfessionSkillAdditionMap
     * @return
     */
    private static BigInteger getGrandChildProfessionAddAbility(int occupation , Map<Integer, BigInteger> grandChildProfessionSkillAdditionMap) {
        if (null == grandChildProfessionSkillAdditionMap){
            return BigInteger.ZERO;
        }

        BigInteger ability = BigInteger.ZERO;
        if(grandChildProfessionSkillAdditionMap.containsKey(occupation)){//加对应职业
            ability = ability.add(grandChildProfessionSkillAdditionMap.get(occupation));
        }

        if(grandChildProfessionSkillAdditionMap.containsKey(0)){//加全部
            ability = ability.add(grandChildProfessionSkillAdditionMap.get(0));
        }
        return ability;
    }

    private static long getWingRoomAddQualification(int patronsOccupation, Map<Integer, UserFurnitureSample> furnitureMap, Map<Integer, UserFurnitureSuitData> suitDataMap) {
        long addValue = 0L;
        //家具加成
        for (UserFurnitureSample sample : furnitureMap.values()) {
            WingRoomFurnitureConfig furnitureConfig = WingRoomConfigMgr.getFurnitureConfig(sample.getFurnitureId());
            if (furnitureConfig == null) {
                continue;
            }
            for (Integer skillId : furnitureConfig.getSkills()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo == null) {
                    continue;
                }
                if (skillInfo.getType() == eSkillType.SkinBeautySkillAddPatronsAbility.getValue() && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == patronsOccupation)) {
                    addValue += SkillMgr.getSkillAddition(skillInfo, sample.getLv());
                }
            }
        }
        //家具套装加成
        for (UserFurnitureSuitData suitData : suitDataMap.values()) {
            Integer skillId = ConfigMgr.getSuitSkillMap().get(suitData.getSuitType());
            if (skillId == null) {
                continue;
            }
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo == null) {
                continue;
            }
            if (skillInfo.getType() == eSkillType.SkinBeautySkillAddPatronsAbility.getValue() && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == patronsOccupation)) {
                addValue += SkillMgr.getSkillAddition(skillInfo, suitData.getSuitLv());
            }
        }
        return addValue;
    }

    //家具套装加门客赚钱千分比
    private static long getWingRoomAddPercentage(int occupation, Map<Integer, UserFurnitureSuitData> suitDataMap) {
        long addValue = 0L;
        //家具套装加成
        for (UserFurnitureSuitData suitData : suitDataMap.values()) {
            Integer skillId = ConfigMgr.getSuitSkillMap().get(suitData.getSuitType());
            if (skillId == null) {
                continue;
            }
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo == null) {
                continue;
            }
            if (skillInfo.getType() == eSkillType.SpecialOccupationPatronsAbilityAddRatio.getValue() && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == occupation)) {
                addValue += SkillMgr.getSkillAddition(skillInfo, suitData.getSuitLv());
            }
        }
        return addValue;
    }

    private static BigInteger getWingRoomAddAbility(int occupation, Map<Integer, UserFurnitureSample> furnitureMap) {
        long addValue = 0L;
        //家具加成
        for (UserFurnitureSample sample : furnitureMap.values()) {
            WingRoomFurnitureConfig furnitureConfig = WingRoomConfigMgr.getFurnitureConfig(sample.getFurnitureId());
            if (furnitureConfig == null) {
                continue;
            }
            for (Integer skillId : furnitureConfig.getSkills()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo == null) {
                    continue;
                }
                if (skillInfo.getType() == eSkillType.PatronsCookSkill.getValue() && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == occupation)) {
                    addValue += SkillMgr.getSkillAddition(skillInfo, sample.getLv());
                }
            }
        }
        return BigInteger.valueOf(addValue);
    }

    public static boolean isPatronsTwins(int patronsId){
        PatronsInfo patronsInfo = getPatronsInfo(patronsId);
        if(null != patronsInfo){
            return patronsInfo.isTwins();
        }
        return false;
    }

    public static Map<Integer, PatronsStage> getPatronsStageMap() {
        return patronsStageMap;
    }

    /**
    * 描述：获取双生皮肤信息
    * 作者：zrq
    * 时间：2022/1/4
    * 参数：
    玩家皮肤信息
    * 返回值：双生皮肤信息
    **/
    private static Map<Integer, List<Integer>> getTwinsSkinMap(Map<Integer, UserSkin> userSkinMap){
        Map<Integer, List<Integer>> twinsSkinMap = new ConcurrentHashMap<>();
        for (UserSkin userSkin : userSkinMap.values()) {
            SkinInfo skinInfo = SkinMgr.getSkinInfo(userSkin.getSkinId());
            if(null != skinInfo){
                if(skinInfo.getTwinsId() > 0){
                    twinsSkinMap.put(skinInfo.getSkinId(), new ArrayList<>());
                    List<Integer> twinsSkinList = twinsSkinMap.get(skinInfo.getSkinId());
                    twinsSkinList.add(skinInfo.getSkinId());
                    if(userSkinMap.containsKey(skinInfo.getTwinsId())){
                        if(!twinsSkinList.contains(skinInfo.getTwinsId())) {
                            twinsSkinList.add(skinInfo.getTwinsId());
                        }
                    }
                }
            }
        }
        return twinsSkinMap;
    }

    private static BigInteger getWineryAddAbility(int occupation, Map<Integer, ExtensionWineryItemInfo> wineryItemInfoMap) {
        long addValue = 0L;
        //酒坊加成
        for (ExtensionWineryItemInfo v : wineryItemInfoMap.values()) {
            SkillInfo skillInfo = SkillMgr.getSkillWith(eSkillType.PatronsCookSkill.getValue(), v.getId());
            if (skillInfo == null) {
                continue;
            }
            if (skillInfo.getType() == eSkillType.PatronsCookSkill.getValue() && (skillInfo.getParamList().get(2) == 0 || skillInfo.getParamList().get(2) == occupation)) {
                addValue += SkillMgr.getSkillAddition(skillInfo, v.getLevel());
            }
        }
        return BigInteger.valueOf(addValue);
    }

    /**
     * 蛐蛐技能增加门客赚钱千分比
     * @param userPatrons
     * @return
     */
    public static double getCricketSkillAddRatio(UserPatrons userPatrons){
        double addRatio = 0;
        for (UserPatronsSkill patronsSkill : userPatrons.getSkillList()) {
            if (patronsSkill.getType() != ePatronsSkillType.Cricket.getValue()) {
                continue;
            }
            int skillId = patronsSkill.getSkillId();
            CricketConfig cricketConfig = CricketMgr.getCricketConfigByPartonSkill(skillId);
            if (cricketConfig != null) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null) {
                    String skillParam = CricketMgr.getPartonSkillParam(skillInfo.getStars(), StringUtils.string2intSafe(patronsSkill.getExtraParams(), 0));
                    List<String> paramList = StringUtils.stringToStringList(skillParam, ";");
                    addRatio += Long.parseLong(paramList.get(2));
                }
            }
        }
        return addRatio;
    }

    /**
     * 蛐蛐技能增加门客固定赚钱
     * @param userPatrons
     * @return
     */
    private static BigInteger getCricketAddAbility(UserPatrons userPatrons) {
        long addValue = 0L;
        for (UserPatronsSkill patronsSkill : userPatrons.getSkillList()) {
            if (patronsSkill.getType() != ePatronsSkillType.Cricket.getValue()) {
                continue;
            }
            int skillId = patronsSkill.getSkillId();
            CricketConfig cricketConfig = CricketMgr.getCricketConfigByPartonSkill(skillId);
            if (cricketConfig != null) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null) {
                    String skillParam = CricketMgr.getPartonSkillParam(skillInfo.getStars(), StringUtils.string2intSafe(patronsSkill.getExtraParams(), 0));
                    List<String> paramList = StringUtils.stringToStringList(skillParam, ";");
                    addValue += Long.parseLong(paramList.get(1));
                }
            }
        }
        return BigInteger.valueOf(addValue);
    }

    private static long getVehicleSoulAddAbility(UserPatrons userPatrons,Map<String, UserVehicle> userVehicleMap,Map<Integer,UserVehicleSoul> userVehicleSoulMap) {
        long addValue = 0L;
        UserVehicle userVehicle = null;
        for(UserVehicle temVehicle : userVehicleMap.values()){
            if(temVehicle.getPatronsId() == userPatrons.getPatronsId()){
                userVehicle = temVehicle;
            }
        }
        if(userVehicle == null){
            return 0;
        }
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        if(vehicleInfo.getQuality() < 6){
            //不是無雙的直接不用算了，減少消耗
            return 0;
        }
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
        for(UserVehicleSoul userVehicleSoul : userVehicleSoulMap.values()){
            if(!userVehicleSoul.isDelete() && userVehicleSoul.getVehicleId().equals(userVehicle.getVehicleUid())){
                Map<Integer, List<Integer>> entryMap = userVehicleSoul.getEntryMap();
                for(List<Integer> infoList : entryMap.values()){
                    if(infoList.get(1) == patronsInfo.getOccupation()){
                        addValue = addValue + infoList.get(2);
                    }
                }
            }
        }
        return addValue;
    }

    ////兽魂加资质日志获取加成值
    public static long getVehicleSoulAddAbility(UserPatrons userPatrons,UserVehicle userVehicle,Map<Integer,UserVehicleSoul> userVehicleSoulMap) {
        long addValue = 0L;
        if(userVehicle == null){
            return 0;
        }
        VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
        if(vehicleInfo.getQuality() < 6){
            //不是無雙的直接不用算了，減少消耗
            return 0;
        }
        PatronsInfo patronsInfo = PatronsMgr.getPatronsInfo(userPatrons.getPatronsId());
        for(UserVehicleSoul userVehicleSoul : userVehicleSoulMap.values()){
            if(!userVehicleSoul.isDelete() && userVehicleSoul.getVehicleId().equals(userVehicle.getVehicleUid())){
                Map<Integer, List<Integer>> entryMap = userVehicleSoul.getEntryMap();
                for(List<Integer> infoList : entryMap.values()){
                    if(infoList.get(1) == patronsInfo.getOccupation()){
                        addValue = addValue + infoList.get(2);
                    }
                }
            }
        }
        return addValue;
    }

    public static List<Integer> calUnlockSkill(UserPatrons userPatrons, PatronsInfo patronsInfo){
        List<Integer> unlockList = new ArrayList<>();
        for (PatronsUnlockSkill unlockSkillInfo : patronsInfo.getUnlockSkillList()) {
            for (UserPatronsSkill skill : userPatrons.getSkillList()) {
                if(skill.getSkillId() == unlockSkillInfo.getSrcSkillId()){
                    if(unlockSkillInfo.getUnlockType() == 1){
                        if(skill.getSkillLv() >= unlockSkillInfo.getLimitLv()){
                            unlockList.add(unlockSkillInfo.getSkillId());
                        }
                    }
                }
            }
        }
        return unlockList;
    }

    /**
     * 获取门客品质
     */
    public static int getPatronsQuality(UserPatrons patrons) {
        if (patrons == null) {
            return 0;
        }
        int quality = 0;
        PatronsInfo patronsInfo = getPatronsInfo(patrons.getPatronsId());
        if (null != patronsInfo) {
            quality = patronsInfo.getQuality();
        }
        if (patrons.getShowPromotionId() > 0) {
            PromotionInfo promotionInfo = PromotionMgr.getPromotionInfoById(patrons.getShowPromotionId());
            if (null != promotionInfo) {
                quality = promotionInfo.getQuality();
            }
        }
        return quality;
    }

    /**
     * 美女妙音坊门客技能增加赚钱固定值
     * @param userPatrons
     * @param beautyMap
     * @return
     */
    private static long getBeautyMusicRoomAddRegular(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                for (Map.Entry<Integer, BigInteger> entry : beauty.getMusicRoomSkill().getGoods().entrySet()) {
                    int skillId = entry.getKey();
                    int skillLv = entry.getValue().intValue();
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (skillInfo == null) {
                        continue;
                    }
                    if (skillInfo.getType() != eSkillType.BeautyPatronsEscortSkill1.getValue()){
                        continue;
                    }
                    long addregular = SkillMgr.getSkillAddition(skillInfo, skillLv);
                    regular += addregular;
                }
            }
        }
        return regular;
    }

    /**
     * 美女妙音坊门客技能增加赚钱百分比
     */
    private static long getBeautyMusicRoomAddPercentage(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if(null == userPatrons || null == beautyMap){
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                for (Map.Entry<Integer, BigInteger> entry : beauty.getMusicRoomSkill().getGoods().entrySet()) {
                    int skillId = entry.getKey();
                    int skillLv = entry.getValue().intValue();
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (skillInfo == null) {
                        continue;
                    }
                    if (skillInfo.getType() != eSkillType.BeautyPatronsSkill2.getValue()){
                        continue;
                    }
                    long addregular = SkillMgr.getSkillAddition(skillInfo, skillLv);
                    regular += addregular;
                }
            }
        }
        return regular;
    }

    /**
     * 美女妙音坊门客技能增加资质
     */
    private static long getBeautyMusicRoomAddQualification(UserPatrons userPatrons, Map<Integer, UserBeauty> beautyMap) {
        if (null == userPatrons || null == beautyMap) {
            return 0;
        }
        long regular = 0;
        for (UserBeauty beauty : beautyMap.values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                for (Map.Entry<Integer, BigInteger> entry : beauty.getMusicRoomSkill().getGoods().entrySet()) {
                    int skillId = entry.getKey();
                    int skillLv = entry.getValue().intValue();
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                    if (skillInfo == null) {
                        continue;
                    }
                    if (skillInfo.getType() != eSkillType.BeautyPatronsEscortSkill2.getValue()) {
                        continue;
                    }
                    long addregular = SkillMgr.getSkillAddition(skillInfo, skillLv);
                    regular += addregular;
                }
            }
        }
        return regular;
    }

    public static void printfPatronsAbilityToChat(GamePlayer player, UserPatrons userPatrons, CalcPatronsAbilityParam param) {

        PatronsAbilityCalcBaseParams patronsAbilityCalcBaseParams = calcPatronsAbilityCalcBaseParams(userPatrons, param, true);
        StringBuilder printfStr = new StringBuilder(patronsAbilityCalcBaseParams.getPrintfStr());

        BigDecimal baseAbility = patronsAbilityCalcBaseParams.calcBaseAbility();
        BigDecimal calcAbilityParam = patronsAbilityCalcBaseParams.getCalcAbilityParam();
        BigDecimal abilityAdditionRatio = patronsAbilityCalcBaseParams.getAbilityAdditionRatio();

        //算出原美女缘分技能增加的赚钱值，再算美女无双技能生效的值。
        BigDecimal totalPeerlessAddition = BigDecimal.ZERO;
        for (UserBeauty beauty : param.getBeautyMap().values()) {
            if (BeautyMgr.beautyAndPatronsHasRelation(beauty, userPatrons)) {//美女关系
                printfStr.append("美女无双技能加成").append(beauty.getBeautyId()).append("\n");

                //魅力值技能
                int level1 = beauty.getSkill1();
                List<Integer> beautySkillList = StringUtils.stringToIntegerList(GameConfig.BEAUTY_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo1 = SkillMgr.getSkillInfo(beautySkillList.get(0));
                BigDecimal skillAddition1 = BigDecimal.valueOf(SkillMgr.getSkillAddition(skillInfo1, level1));
                int level2 = beauty.getSkill2();
                SkillInfo skillInfo2 = SkillMgr.getSkillInfo(beautySkillList.get(1));
                BigDecimal skillAddition2 = BigDecimal.valueOf((double) SkillMgr.getSkillAddition(skillInfo2, level2) / 1000)
                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP)
                        .multiply(baseAbility)
                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);

                printfStr.append("缘分技能总值：").append(skillAddition1.toString()).append(" + ").append(skillAddition2.toString()).append(" = ").append(skillAddition1.add(skillAddition2).toString()).append("\n");

                //押镖技能
                int escortSkillLevel1 = beauty.getEscortSkill1();
                List<Integer> escortSkill1 = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                SkillInfo skillInfo = SkillMgr.getSkillInfo(escortSkill1.get(0));
                BigDecimal escortSkill1Addition = BigDecimal.valueOf(SkillMgr.getSkillAddition(skillInfo, escortSkillLevel1));

                int escortSkillLevel2 = beauty.getEscortSkill2();
                List<Integer> escortSkill2 = StringUtils.stringToIntegerList(GameConfig.BEAUTY_ESCORT_PATRONS_SKILL, "\\|");
                SkillInfo escortSkill2Info2 = SkillMgr.getSkillInfo(escortSkill2.get(1));
                BigDecimal escortSkill2Addition = BigDecimal.valueOf(SkillMgr.getSkillAddition(escortSkill2Info2, escortSkillLevel2))
                        .multiply(calcAbilityParam)
                        .multiply(BigDecimal.ONE.add(abilityAdditionRatio))
                        .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                BigDecimal totalAddition = skillAddition1.add(skillAddition2).add(escortSkill1Addition).add(escortSkill2Addition);
                printfStr.append("押镖技能总值：").append(escortSkill1Addition.toString()).append(" + ").append(escortSkill2Addition.toString()).append(" = ").append(escortSkill1Addition.add(escortSkill2Addition).toString()).append("\n");

                //妙音坊技能
                BigDecimal musicRoomAddition = BigDecimal.ZERO;
                for (Map.Entry<Integer, BigInteger> entry : beauty.getMusicRoomSkill().getGoods().entrySet()) {
                    int skillId = entry.getKey();
                    int skillLv = entry.getValue().intValue();
                    SkillInfo musicRoomSkillInfo = SkillMgr.getSkillInfo(skillId);
                    if (musicRoomSkillInfo == null) {
                        continue;
                    }
                    printfStr.append("妙音坊技能：").append(skillId).append(" 等级：").append(skillLv).append("\n");
                    int skillAddition = SkillMgr.getSkillAddition(musicRoomSkillInfo, skillLv);
                    if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsEscortSkill1.getValue()){
                        //加固定值
                        musicRoomAddition = musicRoomAddition.add(BigDecimal.valueOf(skillAddition));
                        printfStr.append("妙音坊技能加固定值：").append(skillAddition).append("\n");
                    } else if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsSkill2.getValue()){
                        //加百分比
                        BigDecimal musicAddition = BigDecimal.valueOf((double) skillAddition / 1000)
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP)
                                .multiply(baseAbility)
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                        musicRoomAddition = musicRoomAddition.add(musicAddition);
                        printfStr.append("妙音坊技能加百分比：").append(skillAddition).append("x").append(baseAbility.toString()).append("=").append(musicAddition.toString()).append("\n");
                    } else if (musicRoomSkillInfo.getType() == eSkillType.BeautyPatronsEscortSkill2.getValue()){
                        //加资质
                        BigDecimal musicAddition = BigDecimal.valueOf(skillAddition)
                                .multiply(calcAbilityParam)
                                .multiply(BigDecimal.ONE.add(abilityAdditionRatio))
                                .setScale(CalculationManager.CALCULATION_SCALE, BigDecimal.ROUND_UP);
                        musicRoomAddition = musicRoomAddition.add(musicAddition);
                        printfStr.append("妙音坊技能加资质：").append(skillAddition).append("x").append(calcAbilityParam.toString()).append("x").append(BigDecimal.ONE.add(abilityAdditionRatio).toString()).append("=").append(musicAddition.toString()).append("\n");
                    }
                }
                printfStr.append("妙音坊技能总值：").append(musicRoomAddition.toString()).append("\n");
                totalAddition = totalAddition.add(musicRoomAddition);
                printfStr.append("缘分总值：").append(totalAddition.toString()).append("\n");

                if (beauty.getPeerlessUp() > 0) {
                    BigDecimal additionByPeerlessSkill = BeautyMgr.getBeautyPeerlessSkillAddition(totalAddition,
                            beauty, userPatrons);
                    printfStr.append("无双技能额外加成：").append(additionByPeerlessSkill.toString()).append("\n");

                    totalPeerlessAddition = totalPeerlessAddition.add(additionByPeerlessSkill);
                }
            }
        }
        BigDecimal peerlessSkillAddition =totalPeerlessAddition;
        printfStr.append("无双技能提供总值：").append(peerlessSkillAddition.toString()).append("\n");

        printfStr.append("门客总赚钱：").append(userPatrons.getAbility()).append("\n");

        String content = printfStr.toString();
        WorldMessageProto.WorldMessageTempMsg.Builder msg = WorldMessagePb.parseWorldMessageTempMsg(player.getUserInfo(), eMessageType.WorldChat.getValue(), eChatContentType.Common.getContentType(), content, DateHelper.getCurrentTime(), 0, "");
        player.sendPacket(ClientProtocol.U_WORLD_MESSAGE_SYNC, msg);
    }

    private static long getCurioSkillAdd(UserPatrons userPatrons, Map<Integer, UserCurioSkillData> curioSkillDataMap, int skillType, int params3) {
        long add = 0;
        for (Map.Entry<Integer, UserCurioSkillData> entry : curioSkillDataMap.entrySet()) {
            UserCurioSkillData skillData = entry.getValue();
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillData.getSkill());
            if(skillInfo == null){
                continue;
            }
            if(skillInfo.getType() == skillType){
                //套装技能特殊处理
                if(skillData.getSkillType() == eCurioSkillType.CurioItemSuitSkill.getType() && skillInfo.getParamList().get(2) == 0){
                    //拿藏品套装
                    if(isInSuitInfoSpecialId(params3, skillData)){
                        add += skillData.getAddition();
                    }
                    continue;
                }

                if(params3 == 0 || params3 == skillInfo.getParamList().get(2) || skillInfo.getParamList().get(2) == 0){
                    add += skillData.getAddition();
                }
            }
        }
        CurioMgr.debugLog(userPatrons.getUserId(), skillType, add);
        return add;
    }

    private static long getCurioSkillAdd(UserPatrons userPatrons, Map<Integer, UserCurioSkillData> curioSkillDataMap, Map<Integer, Integer> skillParamMap) {
        long add = 0;
        for (Map.Entry<Integer, UserCurioSkillData> entry : curioSkillDataMap.entrySet()) {
            UserCurioSkillData skillData = entry.getValue();
            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillData.getSkill());
            if(skillInfo == null){
                continue;
            }
            if(skillParamMap.containsKey(skillInfo.getType())){
                int params3 = skillParamMap.get(skillInfo.getType());
                //套装技能特殊处理
                if(skillData.getSkillType() == eCurioSkillType.CurioItemSuitSkill.getType() && skillInfo.getType() == eSkillType.CurioComPatronsEarnAddSkill.getValue()){
                    //拿藏品套装
                    if(isInSuitInfoSpecialId(params3, skillData)){
                        add += skillData.getAddition();
                    }
                    continue;
                }

                if(params3 == 0 || params3 == skillInfo.getParamList().get(2) || skillInfo.getParamList().get(2) == 0){
                    add += skillData.getAddition();
                }

                CurioMgr.debugLog(userPatrons.getUserId(), skillInfo.getType(), add);
            }
        }

        return add;
    }

    /**
     * 技能 是否在套装内指定的id 才有生效
     * @param params3 特性生效的id
     * @param skillData 当前技能
     * @return
     */
    private static boolean isInSuitInfoSpecialId(int params3, UserCurioSkillData skillData) {
        //套装
        CurioItemSuitInfo suitInfo = CurioConfigMgr.getConfig().getCurioItemSuitInfo(skillData.getObjId());
        if(suitInfo == null){
            return false;
        }
        boolean inSuitSpecialId = false;
        //藏品
        for (Integer itemId : suitInfo.getCurioList()) {
            CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemId);
            if(itemInfo == null || itemInfo.getBaseSkill() <= 0){
                continue;
            }
            //找基础技能生效的特定id
            SkillInfo baseSkillInfo = SkillMgr.getSkillInfo(itemInfo.getBaseSkill());
            if(baseSkillInfo != null && baseSkillInfo.getParamList().get(2) == params3){
                inSuitSpecialId = true;
            }
        }
        return inSuitSpecialId;
    }

    /**
     * 找到门客等级能对应的最大突破等级
     * @param patronsLv
     * @return
     */
    public static PatronsBreak findPatronsLvMaxBreakLv(int patronsLv) {
        PatronsBreak findBreak = null;
        for (int i = 0; i < 500; i++) {
            PatronsBreak patronsBreak = PatronsMgr.getPatronsBreak(i);
            if(patronsBreak == null){
                break;
            }
            findBreak = patronsBreak;
            if (findBreak.getCurrentMaxLv() > patronsLv) {
                break;
            }
        }

        return findBreak;
    }

    /**
     * 获得门客的契约赚钱值
     *
     * @param userPatrons
     * @param param
     * @return
     */
    public static BigDecimal calcPatronsContractTotalAbility(UserPatrons userPatrons, CalcPatronsAbilityParam param) {
        BigDecimal totalAdd = BigDecimal.ZERO;
        if (userPatrons.getPatronsContractMap().isEmpty()) {//没契约的就不要计算了
            return totalAdd;
        }

        int skill204Addition = getUserPatronsFoxSkill204Addition(userPatrons);

        for (UserPatronsContract patronsContract : userPatrons.getPatronsContractMap().values()) {
            if (patronsContract.getBeautyId() == 0) {
                continue;
            }

            UserBeauty userBeauty = param.getBeautyMap().get(patronsContract.getBeautyId());
            if (userBeauty == null) {
                continue;
            }
            BigDecimal beautyTotalRelationAbility = BeautyMgr.calcBeautyTotalAddRelationPatronsAbility(userBeauty, param);
            BigDecimal contractAdd = beautyTotalRelationAbility.multiply(BigDecimal.valueOf(skill204Addition).divide(BigDecimal.valueOf(1000))).setScale(0, BigDecimal.ROUND_UP);
            patronsContract.setAbilityAdd(contractAdd.toBigInteger());
            totalAdd = totalAdd.add(contractAdd);
        }
        return totalAdd;
    }

    /**
     * 获得门客提升契约的千分比
     *
     * @param userPatrons
     * @return
     */
    public static int getUserPatronsFoxSkill204Addition(UserPatrons userPatrons) {
        for (UserPatronsSkill userPatronsSkill : userPatrons.getSkillList()) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(userPatronsSkill.getSkillId());
            if (skillInfo == null) {
                continue;
            }
            if (skillInfo.getType() == eSkillType.FoxSkill204.getValue()) {
                return SkillMgr.getSkillAddition(skillInfo, userPatronsSkill.getSkillLv());
            }
        }
        return 0;
    }

    /**
     * 获得门客装配的魂骨提升的赚钱千分比
     */
    public static long getVehicleBoneAddition(UserPatrons userPatrons, Map<String, UserVehicle> vehicleMap, Map<Integer, UserVehicleBone> vehicleBoneMap, int curioAddition) {
        long addValue = 0;
        for (UserVehicle userVehicle : vehicleMap.values()) {
            if (userVehicle.getPatronsId() != userPatrons.getPatronsId()) {
                continue;
            }

            for (UserVehicleBone vehicleBone : vehicleBoneMap.values()) {
                if (vehicleBone.getVehicleId().equals(userVehicle.getVehicleUid())) {
                    long boneAdd = calcBoneSkillAddValue(vehicleBone, eSkillType.BeautyPatronsSkill2);
                    addValue += boneAdd;
                }
            }
        }
        return addValue;
    }

    /**
     * 获得门客魂骨系统加的资质, 有珍兽炼魂资质, 魂骨孔位填充加的资质, 魂骨提供的资质
     *
     * @param userPatrons
     * @param vehicleMap
     * @param vehicleBoneMap
     * @return
     */
    public static long getVehicleBoneAddQuality(UserPatrons userPatrons, Map<String, UserVehicle> vehicleMap, Map<Integer, UserVehicleBone> vehicleBoneMap) {
        long addQuality = 0;
        for (UserVehicle userVehicle : vehicleMap.values()) {
            if (userVehicle.getPatronsId() != userPatrons.getPatronsId()) {
                continue;
            }

            if (userVehicle.getBoneLv() > 0) {//炼魂等级提供资质
                VehicleInfo vehicleInfo = VehicleMgr.getVehicleInfo(userVehicle.getTemplateId());
                if (vehicleInfo == null) {
                    break;
                }

                SkillInfo skillInfo = SkillMgr.getSkillInfo(vehicleInfo.getBonePowerSkill());
                if (skillInfo == null) {
                    break;
                }

                if (skillInfo.getType() != eSkillType.Qualification.getValue()) {
                    break;
                }
                int skillAddition = SkillMgr.getSkillAddition(skillInfo, userVehicle.getBoneLv());
                addQuality += skillAddition;
            }

            List<UserVehicleBone> boneList = new ArrayList<>();
            int starAmount = 0;
            for (UserVehicleBone vehicleBone : vehicleBoneMap.values()) {
                if (vehicleBone.getVehicleId().equals(userVehicle.getVehicleUid())) {
                    long boneAddQuality = calcBoneSkillAddValue(vehicleBone, eSkillType.Qualification);
                    addQuality += boneAddQuality;
                    boneList.add(vehicleBone);

                    GoodsInfo goodsInfo = GoodsMgr.getGoodsById(vehicleBone.getConfigId());
                    if (goodsInfo != null) {
                        starAmount += VehicleBoneConfigMgr.getBoneSuitStar(goodsInfo);
                    }
                }
            }

            long holdFullAdd = VehicleBoneConfigMgr.calcHoleFullAddQualification(userVehicle.getBoneLv(), boneList.size(), starAmount, userVehicle.getBoneHole());
            addQuality += holdFullAdd;
        }
        return addQuality;
    }

    public static long calcBoneSkillAddValue(UserVehicleBone bone, eSkillType skillType) {
        long addValue = 0;
        for (Map.Entry<Integer, Integer> entry : bone.getSkillMap().entrySet()) {
            int skillId = entry.getKey();
            int lv = entry.getValue();

            SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
            if (skillInfo == null) {
                continue;
            }

            if (skillInfo.getType() != skillType.getValue()) {
                continue;
            }

            addValue += SkillMgr.getSkillAddition(skillInfo, lv);
        }
        return addValue;
    }


    /**
     * 获得门客装配的魂骨加的固定赚钱
     *
     * @param userPatrons
     * @param vehicleBoneMap
     * @return
     */
    private static BigInteger getVehicleBoneAddAbility(UserPatrons userPatrons, Map<String, UserVehicle> vehicleMap, Map<Integer, UserVehicleBone> vehicleBoneMap) {
        long addValue = 0;
        for (UserVehicle userVehicle : vehicleMap.values()) {
            if (userVehicle.getPatronsId() != userPatrons.getPatronsId()) {
                continue;
            }

            for (UserVehicleBone vehicleBone : vehicleBoneMap.values()) {
                if (vehicleBone.getVehicleId().equals(userVehicle.getVehicleUid())) {
                    long boneAdd = calcBoneSkillAddValue(vehicleBone, eSkillType.BeautyPatronsEscortSkill1);
                    addValue += boneAdd;
                }
            }
        }
        return BigInteger.valueOf(addValue);
    }

    /**
     * 是否是有凤魁的组合门客
     *
     * @param patronsId
     * @return
     */
    public static boolean haveCombLeader(int patronsId) {
        PatronsInfo patronsInfo = getPatronsInfo(patronsId);
        if (patronsInfo == null) {
            return false;
        }
        if (patronsInfo.getCombId() == 0) {
            return false;
        }

        PromotionInfo promotionInfo = PromotionMgr.getCharacterNextPromotion(patronsInfo.getCombId(), 0);
        if (promotionInfo == null || promotionInfo.getType() != 14) { //暂时写死类型14才是
            return false;
        }

        return true;
    }

    public static int getPatronsCombId(int patronsId) {
        PatronsInfo patronsInfo = getPatronsInfo(patronsId);
        if (patronsInfo == null) {
            return 0;
        }
        return patronsInfo.getCombId();
    }

    /**
     * 获得凤魁的技能列表
     */
    public static Map<Integer, Integer> getCombLeaderSkillMap(int patronsId, Map<Integer, UserCombLeaderData> leaderDataMap) {
        int combId = getPatronsCombId(patronsId);
        UserCombLeaderData leaderData = leaderDataMap.get(combId);
        if (leaderData == null) {
            return new HashMap<>();
        }

        Map<Integer, Integer> skillMap = new HashMap<>();
        for (CombLeaderSkill leaderSkill : leaderData.getSkillMap().values()) {
            skillMap.put(leaderSkill.getId(), leaderSkill.getLv() + leaderSkill.getSkinLv());
        }
        return skillMap;
    }

    /**
     * 这里是给看门客详情用的
     * @param userId
     * @return
     */
    public static CalcPatronsAbilityParam buildCalcPatronsAbilityParam(long userId, int patronsId) {
        GamePlayer gamePlayer = GamePlayerMgr.getOnlinePlayer(userId);
        if (gamePlayer != null) {
            return gamePlayer.getModule(PatronsModule.class).buildCalcPatronsAbilityParam();
        }else {
            CalcPatronsAbilityParam.CalcPatronsAbilityParamBuilder builder = CalcPatronsAbilityParam.CalcPatronsAbilityParamBuilder.aCalcPatronsAbilityParam();

            Map<Integer, UserBeauty> userBeautyMap = UserBeautyBussiness.getUserBeautyMap(userId);
            try {
                //指定国内渠道屏蔽同时拥有美女103001和103209的,屏蔽103209
                int channelId = ServerListMgr.getChannelId(GameServer.getInstance().getServerId());
                if (
                        channelId == 201 ||
                                channelId == 221 ||
                                channelId == 231 ||
                                channelId == 241 ||
                                channelId == 301 ||
                                channelId == 311 ||
                                channelId == 321) {
                    if (userBeautyMap.containsKey(103001)){
                        userBeautyMap.remove(103209);
                    }
                }
            } catch (Exception e) {
                logger.error(e);
            }
            Map<Integer, CricketData> cricketDataMap = UserCricketBussiness.getCricketDataMap(userId);
            Map<Integer, List<CricketEquipSkill>> eSkillMap = UserCricketBussiness.getCricketEquipSkillMap(userId);
            for(Integer cricketId : eSkillMap.keySet()){
                if(cricketDataMap.containsKey(cricketId)){
                    cricketDataMap.get(cricketId).setEquipSkillList(eSkillMap.get(cricketId));
                }
            }

            builder.withUserSkinMap(UserSkinBusiness.getUserSkinMap(userId))
                    .withPatronsMap(UserPatronsBussiness.getUserPatronsAndSkillMap(userId))
                    .withVehicleMap(UserVehicleBussiness.getUserVehicleAndSkillMap(userId, patronsId))
                    .withBeautyMap(userBeautyMap)
//                    .withUserDishesMap(player.getModule(InnModule.class).getUserDishesMap())//门客详情用不到
                    .withManorTechnologyDataMap(UserManorBusiness.getTechnologyDataMap(userId))
//                    .withEmbroideryMeter(player.getModule(SkinVolumeModule.class).getSkinVolumeData().getEmbroideryMeter())//门客详情用不到
//                    .withUserLTPMainRoleSkinMap(player.getModule(SkinModule.class).getUserLTPMainRoleSkinMap())//门客详情用不到
                    .withFishDataMap(UserFishPondBusiness.getFishDataMap(userId, patronsId))
//                    .withGrandChildProfessionSkillAdditionMap(player.getModule(GrandChildModule.class).getGrandChildProfessionAddAbilityMap())//门客详情用不到
//                    .withUserAssistantSuitMap(player.getModule(AssistantSkinModule.class).getAssistantSuitMap())//门客详情用不到
//                    .withFurnitureMap(player.getModule(WingRoomModule.class).getFurnitureMap())//门客详情用不到
                    .withSuitDataMap(new UserFurnitureSuitDaoImpl().getUserFurnitureSuitMap(userId))
//                    .withWineryItemInfoMap(player.getModule(WineryModule.class).getUserWineryItemInfoMap())//门客详情用不到
                    .withCricketDataMap(cricketDataMap)
                    .withUserPatronsSkinBondDataMap(new UserPatronsSkinBondDaoImpl().getUserPatronsSkinBond(userId))
                    .withUserVehicleSoulMap(UserVehicleSoulBussiness.getUserVehicleSoulEquipMap(userId))
                    .withUserVehicleBoneMap(new UserVehicleBoneDaoImpl().getUserVehicleEquipBone(userId))
                    .withWingRoomChakraAbilityAddMap(WingRoomChakraMgr.getPatronsAddValueMap(userId, WingRoomPositionTypeEnum.POSITION_TYPE_SX))
//                    .withWingRoomChakraQualificationAddMap(WingRoomChakraMgr.getPatronsAddValueMap(player.getUserId(), WingRoomPositionTypeEnum.POSITION_TYPE_MG))////门客详情用不到
                    .withCurioSkillDataMap(new UserCurioSkillDataDaoImpl().getUserCurioSkillData(userId))
                    .withCombLeaderDataMap(new UserCombLeaderDaoImpl().getUserCombLeaderData(userId))
                    .withTravelBookBeautyMap(new TravelBookUserAlbumDaoImpl().getBeautyMap(userId));

            return builder.build();
        }
    }


    /**
     * 增加多少【资质】，能给门客加多少赚钱
     * @param qualificationNum 多少资质
     * @param userPatrons
     * @param calcPatronsAbilityParam
     * @return
     */
    public static BigDecimal qualificationAddAbility(int qualificationNum, UserPatrons userPatrons, CalcPatronsAbilityParam calcPatronsAbilityParam) {
        //获取计算参数
        PatronsAbilityCalcBaseParams params = calcPatronsAbilityCalcBaseParams(userPatrons, calcPatronsAbilityParam);
        return BigDecimal.valueOf(qualificationNum).multiply(params.getCalcAbilityParam()).multiply(BigDecimal.ONE.add(params.getAbilityAdditionRatio()));
    }

    /**
     * 增加多少【赚钱千分比】，能给门客加多少赚钱
     * @param rate 赚钱千分比
     * @param userPatrons
     * @param calcPatronsAbilityParam
     * @return
     */
    public static BigDecimal rateAddAbility(int rate, UserPatrons userPatrons, CalcPatronsAbilityParam calcPatronsAbilityParam) {
        //获取计算参数
        PatronsAbilityCalcBaseParams params = calcPatronsAbilityCalcBaseParams(userPatrons, calcPatronsAbilityParam);
        //增加的赚钱千分比
        BigDecimal rateAddition = BigDecimal.valueOf(rate).divide(BigDecimal.valueOf(1000));
        //总资质
        BigDecimal qualification = BigDecimal.valueOf(params.getQualification());
        //每点资质增加的赚钱
        BigDecimal calcAbilityParam = params.getCalcAbilityParam();
        //计算
        return rateAddition.multiply(qualification).multiply(calcAbilityParam);
    }

    /**
     * 获取门客皮肤的rankType
     * @param patronsSkinId
     * @return
     */
    public static int getPatronsSkinRankRankType(int patronsSkinId) {
        //皮肤配置
        SkinInfo skinInfo = SkinMgr.getSkinInfo(patronsSkinId);
        if (skinInfo == null) {
            return patronsSkinId;
        }
        if (eSkinType.Patrons.getValue() != skinInfo.getType()) {
            return patronsSkinId;
        }
        //获取门客互斥组，判断是否是【爱徒型门客皮肤】
        List<Set<Integer>> list = getPatronsSkinConflictSetList();
        for (Set<Integer> patronsSkinIds : list) {
            if (patronsSkinIds.contains(patronsSkinId)) {
                //属于【爱徒型门客】皮肤，用第一个门客的皮肤ID
                return patronsSkinIds.iterator().next();
            }
        }
        return patronsSkinId;
    }

    /**
     * 不同门客id，但是属于同一个榜单（爱徒门客）。获取用于这个门客的rankType
     * @param patronsId
     * @return
     */
    public static int getPatronsRankRankType(int patronsId) {
        //获取门客互斥组
        List<Set<Integer>> list = getPatronsConflictSetList();
        for (Set<Integer> patronsIds : list) {
            if (patronsIds.contains(patronsId)) {
                return patronsIds.iterator().next();
            }
        }
        return patronsId;
    }

    /**
     * 不同门客id，但是属于同一个门客（爱徒门客）的配置集合。
     * @return
     */
    public static List<Set<Integer>> getPatronsConflictSetList() {
        List<Set<Integer>> list = new ArrayList<>();
        String patronsConflict = GameConfig.PATRONS_SAME_SHOP_TYPE_PARAM;
        if (StringUtils.isNullOrEmpty(patronsConflict)) {
            return list;
        }
        String[] patronsConflictArr = patronsConflict.split("\\|");//互斥组数组
        for (String patronsConflictStr : patronsConflictArr) {
            Set<Integer> set = new LinkedHashSet<>();
            String[] patronsConflictIds = patronsConflictStr.split(";");
            for (String patronsConflictIdStr : patronsConflictIds) {
                int patronsIncompatibleId = Integer.parseInt(patronsConflictIdStr);
                set.add(patronsIncompatibleId);
            }
            list.add(set);
        }
        return list;
    }

    /**
     * 不同门客皮肤id，但是属于同一个门客皮肤（爱徒门客）的配置集合。
     * @return
     */
    public static List<Set<Integer>> getPatronsSkinConflictSetList() {
        List<Set<Integer>> list = new ArrayList<>();
        String patronsSkinConflict = GameConfig.PATRONS_SKIN_SAME_SHOP_TYPE_PARAM;
        if (StringUtils.isNullOrEmpty(patronsSkinConflict)) {
            return list;
        }
        String[] patronsSkinConflictArr = patronsSkinConflict.split("\\|");//互斥组数组
        for (String patronsSkinConflictStr : patronsSkinConflictArr) {
            Set<Integer> set = new LinkedHashSet<>();
            String[] patronsSkinConflictIds = patronsSkinConflictStr.split(";");
            for (String patronsSkinConflictIdStr : patronsSkinConflictIds) {
                int patronsSkinIncompatibleId = Integer.parseInt(patronsSkinConflictIdStr);
                set.add(patronsSkinIncompatibleId);
            }
            list.add(set);
        }
        return list;
    }

    public static Logger getLogger() {
        return logger;
    }

    public static Map<Integer, AlbumConfig> getAlbumConfigMap() {
        return albumConfigMap;
    }

    public static Map<Integer, List<Map<Integer, Integer>>> getAlbumUpgradeMap() {
        return albumUpgradeMap;
    }

    public static Map<Integer, List<Map<Integer, Integer>>> getSkillExtendLevelMap() {
        return skillExtendLevelMap;
    }
}
